improve newtypes

This commit is contained in:
Nikita Vilunov 2023-02-14 20:07:07 +01:00
parent c845f5d4ca
commit 265b78dc51
3 changed files with 46 additions and 21 deletions

View File

@ -25,9 +25,21 @@ use crate::{
util::table::{AnonTable, Key as AnonKey}, util::table::{AnonTable, Key as AnonKey},
}; };
/// Opaque player identifier. /// Opaque player identifier. Cannot contain spaces, must be shorter than 32.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PlayerId(pub ByteVec); pub struct PlayerId(ByteVec);
impl PlayerId {
pub fn from_bytes(bytes: ByteVec) -> Result<PlayerId> {
if bytes.len() > 32 {
return Err(anyhow::Error::msg("Nickname cannot be longer than 32 symbols"));
}
if bytes.contains(&b' ') {
return Err(anyhow::Error::msg("Nickname cannot contain spaces"));
}
Ok(PlayerId(bytes))
}
pub fn as_bytes(&self) -> &ByteVec { &self.0 }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ConnectionId(pub AnonKey); pub struct ConnectionId(pub AnonKey);

View File

@ -17,7 +17,19 @@ use super::player::{ConnectionId, IncomingPlayerEvent};
/// Opaque room id /// Opaque room id
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RoomId(pub ByteVec); pub struct RoomId(ByteVec);
impl RoomId {
pub fn from_bytes(bytes: ByteVec) -> Result<RoomId> {
if bytes.len() > 32 {
return Err(anyhow::Error::msg("Room name cannot be longer than 32 symbols"));
}
if bytes.contains(&b' ') {
return Err(anyhow::Error::msg("Room name cannot contain spaces"));
}
Ok(RoomId(bytes))
}
pub fn as_bytes(&self) -> &ByteVec { &self.0 }
}
/// Shared datastructure for storing metadata about rooms. /// Shared datastructure for storing metadata about rooms.
#[derive(Clone)] #[derive(Clone)]

View File

@ -152,7 +152,7 @@ async fn handle_registered_socket<'a>(
let mut buffer = vec![]; let mut buffer = vec![];
log::info!("Handling registered user: {user:?}"); log::info!("Handling registered user: {user:?}");
let player_id = PlayerId(user.nickname.clone()); let player_id = PlayerId::from_bytes(user.nickname.clone())?;
let mut connection = players.connect_to_player(player_id.clone()).await; let mut connection = players.connect_to_player(player_id.clone()).await;
ServerMessage { ServerMessage {
@ -214,7 +214,7 @@ async fn handle_registered_socket<'a>(
produce_on_join_cmd_messages( produce_on_join_cmd_messages(
&config, &config,
&user, &user,
&Chan::Global(room.id.0.clone()), &Chan::Global(room.id.as_bytes().clone()),
room, room,
writer, writer,
) )
@ -243,7 +243,7 @@ async fn handle_registered_socket<'a>(
if player_id == author_id { if player_id == author_id {
if let Some(room) = rooms.get_room(&room_id) { if let Some(room) = rooms.get_room(&room_id) {
let room_info = room.get_room_info().await; let room_info = room.get_room_info().await;
let chan = Chan::Global(room_id.0); let chan = Chan::Global(room_id.as_bytes().clone());
produce_on_join_cmd_messages(&config, &user, &chan, &room_info, writer).await?; produce_on_join_cmd_messages(&config, &user, &chan, &room_info, writer).await?;
writer.flush().await?; writer.flush().await?;
} else { } else {
@ -252,8 +252,8 @@ async fn handle_registered_socket<'a>(
} else { } else {
ServerMessage { ServerMessage {
tags: vec![], tags: vec![],
sender: Some(author_id.0.clone()), sender: Some(author_id.as_bytes().clone()),
body: ServerMessageBody::Join(Chan::Global(room_id.0)), body: ServerMessageBody::Join(Chan::Global(room_id.as_bytes().clone())),
}.write_async(writer).await?; }.write_async(writer).await?;
writer.flush().await? writer.flush().await?
} }
@ -262,8 +262,8 @@ async fn handle_registered_socket<'a>(
if player_id != author_id || connection.connection_id != connection_id { if player_id != author_id || connection.connection_id != connection_id {
ServerMessage { ServerMessage {
tags: vec![], tags: vec![],
sender: Some(author_id.0.clone()), sender: Some(author_id.as_bytes().clone()),
body: ServerMessageBody::PrivateMessage { target: Recipient::Chan(Chan::Global(room_id.0)), body: body.as_bytes().to_vec() } body: ServerMessageBody::PrivateMessage { target: Recipient::Chan(Chan::Global(room_id.as_bytes().clone())), body: body.as_bytes().to_vec() }
}.write_async(writer).await?; }.write_async(writer).await?;
writer.flush().await? writer.flush().await?
} }
@ -274,7 +274,7 @@ async fn handle_registered_socket<'a>(
sender: Some(config.server_name.as_bytes().to_vec()), sender: Some(config.server_name.as_bytes().to_vec()),
body: ServerMessageBody::N332Topic { body: ServerMessageBody::N332Topic {
client: user.nickname.clone(), client: user.nickname.clone(),
chat: Chan::Global(room_id.0.clone()), chat: Chan::Global(room_id.as_bytes().clone()),
topic: new_topic, topic: new_topic,
}, },
}.write_async(writer).await?; }.write_async(writer).await?;
@ -315,11 +315,10 @@ async fn handle_incoming_message(
handle_join(&config, &user, user_handle, chan, writer).await?; handle_join(&config, &user, user_handle, chan, writer).await?;
} }
ClientMessage::PrivateMessage { recipient, body } => match recipient { ClientMessage::PrivateMessage { recipient, body } => match recipient {
Recipient::Chan(Chan::Global(room)) => match String::from_utf8(body) { Recipient::Chan(Chan::Global(chan)) => match String::from_utf8(body) {
Ok(body) => { Ok(body) => {
user_handle let room_id = RoomId::from_bytes(chan)?;
.send_message(RoomId(room.clone()), body.clone()) user_handle.send_message(room_id, body.clone()).await
.await
} }
Err(err) => log::warn!("failed to parse incoming message: {err}"), Err(err) => log::warn!("failed to parse incoming message: {err}"),
}, },
@ -327,8 +326,9 @@ async fn handle_incoming_message(
}, },
ClientMessage::Topic { chan, topic } => { ClientMessage::Topic { chan, topic } => {
match chan { match chan {
Chan::Global(ref room) => { Chan::Global(chan) => {
let room = rooms.get_room(&RoomId(room.clone())); let room_id = RoomId::from_bytes(chan)?;
let room = rooms.get_room(&room_id);
if let Some(mut room) = room { if let Some(mut room) = room {
room.set_topic(topic).await; room.set_topic(topic).await;
} }
@ -353,8 +353,9 @@ async fn handle_join(
writer: &mut (impl AsyncWrite + Unpin), writer: &mut (impl AsyncWrite + Unpin),
) -> Result<()> { ) -> Result<()> {
match chan { match chan {
Chan::Global(ref room) => { Chan::Global(chan) => {
let room_info = user_handle.join_room(RoomId(room.clone())).await?; let room_id = RoomId::from_bytes(chan.clone())?;
let room_info = user_handle.join_room(room_id).await?;
} }
Chan::Local(_) => {} Chan::Local(_) => {}
}; };
@ -387,13 +388,13 @@ async fn produce_on_join_cmd_messages(
.write_async(writer) .write_async(writer)
.await?; .await?;
let mut members = if let Some(head) = room_info.members.first() { let mut members = if let Some(head) = room_info.members.first() {
head.0.clone() head.as_bytes().clone()
} else { } else {
user.nickname.clone() user.nickname.clone()
}; };
for i in &room_info.members[1..] { for i in &room_info.members[1..] {
members.push(b' '); members.push(b' ');
members.extend(&i.0); members.extend(i.as_bytes());
} }
ServerMessage { ServerMessage {
tags: vec![], tags: vec![],