From 55b69f4c8afeb466094f7f49baa3de41dda33751 Mon Sep 17 00:00:00 2001 From: Nikita Vilunov Date: Thu, 13 Apr 2023 21:15:48 +0200 Subject: [PATCH] rewrite irc projection to use str --- src/core/player.rs | 21 +++--- src/core/room.rs | 8 +-- src/prelude.rs | 2 +- src/projections/irc/mod.rs | 128 +++++++++++++++++------------------- src/projections/xmpp/mod.rs | 24 +++---- src/protos/irc/client.rs | 102 ++++++++++++++-------------- src/protos/irc/mod.rs | 56 ++++++++-------- src/protos/irc/server.rs | 110 +++++++++++++++---------------- src/protos/xmpp/bind.rs | 4 +- src/protos/xmpp/client.rs | 2 +- 10 files changed, 228 insertions(+), 229 deletions(-) diff --git a/src/core/player.rs b/src/core/player.rs index 9aba662..6f63bb8 100644 --- a/src/core/player.rs +++ b/src/core/player.rs @@ -27,20 +27,23 @@ use crate::{ /// Opaque player identifier. Cannot contain spaces, must be shorter than 32. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)] -pub struct PlayerId(ByteVec); +pub struct PlayerId(Box); impl PlayerId { - pub fn from_bytes(bytes: ByteVec) -> Result { + pub fn from_bytes(bytes: Box) -> Result { if bytes.len() > 32 { return Err(fail("Nickname cannot be longer than 32 symbols")); } - if bytes.contains(&b' ') { + if bytes.contains(' ') { return Err(anyhow::Error::msg("Nickname cannot contain spaces")); } Ok(PlayerId(bytes)) } - pub fn as_bytes(&self) -> &ByteVec { + pub fn as_bytes(&self) -> &Box { &self.0 } + pub fn into_bytes(self) -> Box { + self.0 + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -52,7 +55,7 @@ pub struct PlayerConnection { player_handle: PlayerHandle, } impl PlayerConnection { - pub async fn send_message(&mut self, room_id: RoomId, body: String) -> Result<()> { + pub async fn send_message(&mut self, room_id: RoomId, body: Box) -> Result<()> { self.player_handle .send_message(room_id, self.connection_id.clone(), body) .await @@ -126,7 +129,7 @@ impl PlayerHandle { &self, room_id: RoomId, connection_id: ConnectionId, - body: String, + body: Box, ) -> Result<()> { let (promise, deferred) = oneshot(); let cmd = Cmd::SendMessage { @@ -183,7 +186,7 @@ pub enum Cmd { }, SendMessage { room_id: RoomId, - body: String, + body: Box, promise: Promise<()>, }, ChangeTopic { @@ -208,7 +211,7 @@ pub enum Updates { NewMessage { room_id: RoomId, author_id: PlayerId, - body: String, + body: Box, }, RoomJoined { room_id: RoomId, @@ -285,7 +288,7 @@ impl Player { player_id, connections: AnonTable::new(), my_rooms: HashMap::new(), - banned_from: HashSet::from([RoomId::from_bytes(b"empty".to_vec()).unwrap()]), + banned_from: HashSet::from([RoomId::from_bytes("empty".into()).unwrap()]), rx, handle, rooms, diff --git a/src/core/room.rs b/src/core/room.rs index 87902b9..40269e3 100644 --- a/src/core/room.rs +++ b/src/core/room.rs @@ -24,7 +24,7 @@ impl RoomId { "Room name cannot be longer than 32 symbols", )); } - if bytes.contains(&b' ') { + if bytes.contains(' ') { return Err(anyhow::Error::msg("Room name cannot contain spaces")); } Ok(RoomId(bytes)) @@ -60,7 +60,7 @@ impl RoomRegistry { let room = Room { room_id: room_id.clone(), subscriptions: HashMap::new(), - topic: b"New room".to_vec(), + topic: "New room".into(), }; let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room))); inner.rooms.insert(room_id, room_handle.clone()); @@ -112,7 +112,7 @@ impl RoomHandle { lock.broadcast_update(update, player_id).await; } - pub async fn send_message(&self, player_id: PlayerId, body: String) { + pub async fn send_message(&self, player_id: PlayerId, body: Box) { let lock = self.0.read().await; lock.send_message(player_id, body).await; } @@ -157,7 +157,7 @@ impl Room { self.broadcast_update(update, &player_id).await; } - async fn send_message(&self, author_id: PlayerId, body: String) { + async fn send_message(&self, author_id: PlayerId, body: Box) { tracing::info!("Adding a message to room"); let update = Updates::NewMessage { room_id: self.room_id.clone(), diff --git a/src/prelude.rs b/src/prelude.rs index 815a74a..7e3858e 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -11,7 +11,7 @@ pub mod log { pub type Result = std::result::Result; -pub type ByteVec = Vec; +pub type ByteVec = Box; pub fn fail(msg: &str) -> anyhow::Error { anyhow::Error::msg(msg.to_owned()) diff --git a/src/projections/irc/mod.rs b/src/projections/irc/mod.rs index c392269..ecff751 100644 --- a/src/projections/irc/mod.rs +++ b/src/projections/irc/mod.rs @@ -23,19 +23,19 @@ mod test; #[derive(Deserialize, Debug, Clone)] pub struct ServerConfig { pub listen_on: SocketAddr, - pub server_name: String, + pub server_name: Box, } #[derive(Debug)] struct RegisteredUser { - nickname: Vec, + nickname: Box, /** * Username is mostly unused in modern IRC. * * [https://stackoverflow.com/questions/31666247/what-is-the-difference-between-the-nick-username-and-real-name-in-irc-and-wha] */ - username: Vec, - realname: Vec, + username: Box, + realname: Box, } async fn handle_socket( @@ -52,11 +52,11 @@ async fn handle_socket( ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone().into()), body: ServerMessageBody::Notice { - first_target: b"*".to_vec(), + first_target: "*".into(), rest_targets: vec![], - text: b"Welcome to my server!".to_vec(), + text: "Welcome to my server!".into(), }, } .write_async(&mut writer) @@ -83,24 +83,28 @@ async fn handle_registration<'a>( ) -> Result { let mut buffer = vec![]; - let mut future_nickname: Option> = None; - let mut future_username: Option<(Vec, Vec)> = None; + let mut future_nickname: Option> = None; + let mut future_username: Option<(Box, Box)> = None; loop { let res = reader.read_until(b'\n', &mut buffer).await; - match res { + let res = match res { Ok(len) => { if len == 0 { log::info!("Terminating socket"); break Err(anyhow::Error::msg("EOF")); } + match std::str::from_utf8(&buffer[..len]) { + Ok(res) => res, + Err(e) => break Err(e.into()), + } } Err(err) => { log::warn!("Failed to read from socket: {err}"); break Err(err.into()); } - } - let parsed = client_message(&buffer[..]); + }; + let parsed = client_message(res); match parsed { Ok((_, msg)) => { log::info!("Incoming IRC message: {msg:?}"); @@ -154,51 +158,51 @@ async fn handle_registered_socket<'a>( ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N001Welcome { client: user.nickname.clone(), - text: b"Welcome to Kek Server".to_vec(), + text: "Welcome to Kek Server".into(), }, } .write_async(writer) .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N002YourHost { client: user.nickname.clone(), - text: b"Welcome to Kek Server".to_vec(), + text: "Welcome to Kek Server".into(), }, } .write_async(writer) .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N003Created { client: user.nickname.clone(), - text: b"Welcome to Kek Server".to_vec(), + text: "Welcome to Kek Server".into(), }, } .write_async(writer) .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N004MyInfo { client: user.nickname.clone(), - hostname: config.server_name.as_bytes().to_vec(), - softname: b"kek-0.1.alpha.3".to_vec(), + hostname: config.server_name.clone(), + softname: "kek-0.1.alpha.3".into(), }, } .write_async(writer) .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N005ISupport { client: user.nickname.clone(), - params: b"CHANTYPES=#".to_vec(), + params: "CHANTYPES=#".into(), }, } .write_async(writer) @@ -229,7 +233,8 @@ async fn handle_registered_socket<'a>( } else { len }; - if let HandleResult::Leave = handle_incoming_message(&buffer[0..len], &config, &user, &rooms, &mut connection, writer).await? { + let incoming = std::str::from_utf8(&buffer[0..len])?; + if let HandleResult::Leave = handle_incoming_message(incoming, &config, &user, &rooms, &mut connection, writer).await? { break; } buffer.clear(); @@ -246,9 +251,9 @@ async fn handle_registered_socket<'a>( } ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::Error { - reason: b"Leaving the server".to_vec(), + reason: "Leaving the server".into(), }, } .write_async(writer) @@ -315,7 +320,7 @@ async fn handle_update( sender: Some(author_id.as_bytes().clone()), body: ServerMessageBody::PrivateMessage { target: Recipient::Chan(Chan::Global(room_id.as_bytes().clone())), - body: body.as_bytes().to_vec(), + body: body.clone(), }, } .write_async(writer) @@ -325,7 +330,7 @@ async fn handle_update( Updates::RoomTopicChanged { room_id, new_topic } => { ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N332Topic { client: user.nickname.clone(), chat: Chan::Global(room_id.as_bytes().clone()), @@ -357,7 +362,7 @@ enum HandleResult { } async fn handle_incoming_message( - buffer: &[u8], + buffer: &str, config: &ServerConfig, user: &RegisteredUser, rooms: &RoomRegistry, @@ -372,7 +377,7 @@ async fn handle_incoming_message( tags: vec![], sender: None, body: ServerMessageBody::Pong { - from: config.server_name.as_bytes().to_vec(), + from: config.server_name.clone(), token, }, } @@ -387,12 +392,9 @@ async fn handle_incoming_message( handle_part(config, user, user_handle, &chan, writer).await?; } ClientMessage::PrivateMessage { recipient, body } => match recipient { - Recipient::Chan(Chan::Global(chan)) => match String::from_utf8(body) { - Ok(body) => { - let room_id = RoomId::from_bytes(chan)?; - user_handle.send_message(room_id, body.clone()).await?; - } - Err(err) => log::warn!("failed to parse incoming message: {err}"), + Recipient::Chan(Chan::Global(chan)) => { + let room_id = RoomId::from_bytes(chan)?; + user_handle.send_message(room_id, body).await?; }, _ => log::warn!("Unsupported target type"), }, @@ -405,7 +407,7 @@ async fn handle_incoming_message( .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N332Topic { client: user.nickname.clone(), chat: Chan::Global(room_id.as_bytes().clone()), @@ -422,25 +424,22 @@ async fn handle_incoming_message( ClientMessage::Who { target } => match &target { Recipient::Nick(nick) => { // TODO handle non-existing user - let mut username = Vec::with_capacity(nick.len() + 1); - username.push(b'~'); - username.extend_from_slice(nick.as_slice()); - let mut host = b"user/".to_vec(); - host.extend_from_slice(nick.as_slice()); + let mut username = format!("~{nick}"); + let mut host = format!("user/{nick}"); ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: user_to_who_msg(config, user, nick), } .write_async(writer) .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N315EndOfWho { client: user.nickname.clone(), mask: target.clone(), - msg: b"End of WHO list".to_vec(), + msg: "End of WHO list".into(), }, } .write_async(writer) @@ -454,7 +453,7 @@ async fn handle_incoming_message( for member in room_info.members { ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: user_to_who_msg(config, user, member.as_bytes()), } .write_async(writer) @@ -463,11 +462,11 @@ async fn handle_incoming_message( } ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N315EndOfWho { client: user.nickname.clone(), mask: target.clone(), - msg: b"End of WHO list".to_vec(), + msg: "End of WHO list".into(), }, } .write_async(writer) @@ -484,10 +483,10 @@ async fn handle_incoming_message( if nickname == user.nickname { ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N221UserModeIs { client: user.nickname.clone(), - modes: b"+r".to_vec(), + modes: "+r".into(), }, } .write_async(writer) @@ -523,19 +522,16 @@ fn user_to_who_msg( target_user_nickname: &ByteVec, ) -> ServerMessageBody { // Username is equal to nickname - let mut username = Vec::with_capacity(target_user_nickname.len() + 1); - username.push(b'~'); - username.extend_from_slice(target_user_nickname.as_slice()); + let username = format!("~{target_user_nickname}").into(); // User's host is not public, replace it with `user/` pattern - let mut host = b"user/".to_vec(); - host.extend_from_slice(target_user_nickname.as_slice()); + let mut host = format!("user/{target_user_nickname}").into(); ServerMessageBody::N352WhoReply { client: requestor.nickname.clone(), username, host, - server: config.server_name.as_bytes().to_vec(), + server: config.server_name.clone(), flags: AwayStatus::Here, nickname: target_user_nickname.clone(), hops: 0, @@ -559,11 +555,11 @@ async fn handle_join( } else { ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N474BannedFromChan { client: user.nickname.clone(), chan: chan.clone(), - message: b"U dun goofed".to_vec(), + message: "U dun goofed".into(), }, } .write_async(writer) @@ -616,7 +612,7 @@ async fn produce_on_join_cmd_messages( .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N332Topic { client: user.nickname.clone(), chat: chan.clone(), @@ -625,29 +621,29 @@ async fn produce_on_join_cmd_messages( } .write_async(writer) .await?; - let mut members = if let Some(head) = room_info.members.first() { + let mut members: String = if let Some(head) = room_info.members.first() { head.as_bytes().clone() } else { user.nickname.clone() - }; + }.into(); for i in &room_info.members[1..] { - members.push(b' '); - members.extend(i.as_bytes()); + members.push(' '); + members.push_str(i.as_bytes()); } ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N353NamesReply { client: user.nickname.clone(), chan: chan.clone(), - members, + members: members.into(), }, } .write_async(writer) .await?; ServerMessage { tags: vec![], - sender: Some(config.server_name.as_bytes().to_vec()), + sender: Some(config.server_name.clone()), body: ServerMessageBody::N366NamesReplyEnd { client: user.nickname.clone(), chan: chan.clone(), diff --git a/src/projections/xmpp/mod.rs b/src/projections/xmpp/mod.rs index 78dfe6f..8bcc43f 100644 --- a/src/projections/xmpp/mod.rs +++ b/src/projections/xmpp/mod.rs @@ -254,8 +254,8 @@ async fn socket_auth( let _ = xmpp::sasl::Auth::parse(xml_reader, reader_buf).await?; xmpp::sasl::Success.write_xml(xml_writer).await?; Ok(Authenticated { - player_id: PlayerId::from_bytes(b"darova".to_vec())?, - xmpp_name: Name("darova".to_owned()), + player_id: PlayerId::from_bytes("darova".into())?, + xmpp_name: Name("darova".into()), xmpp_resource: Resource("darova".to_owned()), xmpp_muc_name: Resource("darova".to_owned()), }) @@ -337,15 +337,15 @@ async fn socket_final( resource: Some(authenticated.xmpp_resource.clone()), }), from: Some(Jid { - name: Some(Name(std::str::from_utf8(room_id.as_bytes())?.to_owned())), + name: Some(Name(room_id.into_bytes().into())), server: Server("rooms.localhost".into()), - resource: Some(Resource(std::str::from_utf8(author_id.as_bytes())?.to_owned())), + resource: Some(Resource(author_id.into_bytes().into())), }), id: None, r#type: xmpp::client::MessageType::Groupchat, lang: None, subject: None, - body: body, + body: body.into(), } .serialize(&mut events); } @@ -394,8 +394,8 @@ async fn handle_packet( if server.0 == "rooms.localhost" && m.r#type == MessageType::Groupchat { user_handle .send_message( - RoomId::from_bytes(name.0.clone().into_bytes())?, - m.body.clone(), + RoomId::from_bytes(name.0.clone().into())?, + m.body.clone().into(), ) .await?; Message { @@ -413,7 +413,7 @@ async fn handle_packet( r#type: xmpp::client::MessageType::Groupchat, lang: None, subject: None, - body: m.body, + body: m.body.clone(), } .serialize(output); false @@ -446,7 +446,7 @@ async fn handle_packet( }) = p.to { let a = user_handle - .join_room(RoomId::from_bytes(name.0.clone().into_bytes())?) + .join_room(RoomId::from_bytes(name.0.clone())?) .await?; Presence::<()> { to: Some(Jid { @@ -455,7 +455,7 @@ async fn handle_packet( resource: Some(user.xmpp_resource.clone()), }), from: Some(Jid { - name: Some(name), + name: Some(name.clone()), server: Server("rooms.localhost".into()), resource: Some(user.xmpp_muc_name.clone()), }), @@ -483,7 +483,7 @@ async fn handle_iq(output: &mut Vec>, iq: Iq, rooms to: None, r#type: xmpp::client::IqType::Result, body: BindResponse(Jid { - name: Some(Name("darova".to_string())), + name: Some(Name("darova".into())), server: Server("localhost".to_string()), resource: Some(Resource("kek".to_string())), }), @@ -605,7 +605,7 @@ async fn disco_items(to: Option<&str>, req: &ItemQuery, rooms: &RoomRegistry) -> .into_iter() .map(|room_info| Item { jid: Jid { - name: Some(Name(String::from_utf8(room_info.id.into_bytes()).unwrap())), + name: Some(Name(room_info.id.into_bytes())), server: Server("rooms.localhost".to_string()), resource: None, }, diff --git a/src/protos/irc/client.rs b/src/protos/irc/client.rs index 9a316f5..8776394 100644 --- a/src/protos/irc/client.rs +++ b/src/protos/irc/client.rs @@ -9,20 +9,20 @@ pub enum ClientMessage { }, /// PING Ping { - token: ByteVec, + token: Box, }, /// PONG Pong { - token: ByteVec, + token: Box, }, /// NICK Nick { - nickname: ByteVec, + nickname: Box, }, /// USER 0 * : User { - username: ByteVec, - realname: ByteVec, + username: Box, + realname: Box, }, /// JOIN Join(Chan), @@ -37,24 +37,24 @@ pub enum ClientMessage { /// TOPIC : Topic { chan: Chan, - topic: ByteVec, + topic: Box, }, Part { chan: Chan, - message: ByteVec, + message: Box, }, /// PRIVMSG : PrivateMessage { recipient: Recipient, - body: ByteVec, + body: Box, }, /// QUIT : Quit { - reason: ByteVec, + reason: Box, }, } -pub fn client_message(input: &[u8]) -> IResult<&[u8], ClientMessage> { +pub fn client_message(input: &str) -> IResult<&str, ClientMessage> { alt(( client_message_capability, client_message_ping, @@ -71,50 +71,50 @@ pub fn client_message(input: &[u8]) -> IResult<&[u8], ClientMessage> { ))(input) } -fn client_message_capability(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_capability(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("CAP ")(input)?; let (input, subcommand) = capability_subcommand(input)?; Ok((input, ClientMessage::Capability { subcommand })) } -fn client_message_ping(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_ping(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("PING ")(input)?; let (input, token) = token(input)?; Ok(( input, ClientMessage::Ping { - token: token.to_owned(), + token: token.into(), }, )) } -fn client_message_pong(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_pong(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("PONG ")(input)?; let (input, token) = token(input)?; Ok(( input, ClientMessage::Pong { - token: token.to_owned(), + token: token.into(), }, )) } -fn client_message_nick(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_nick(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("NICK ")(input)?; let (input, nickname) = receiver(input)?; Ok(( input, ClientMessage::Nick { - nickname: nickname.to_owned(), + nickname: nickname.into(), }, )) } -fn client_message_user(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_user(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("USER ")(input)?; let (input, username) = receiver(input)?; let (input, _) = tag(" ")(input)?; @@ -127,70 +127,70 @@ fn client_message_user(input: &[u8]) -> IResult<&[u8], ClientMessage> { Ok(( input, ClientMessage::User { - username: username.to_owned(), - realname: realname.to_owned(), + username: username.into(), + realname: realname.into(), }, )) } -fn client_message_join(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_join(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("JOIN ")(input)?; let (input, chan) = chan(input)?; Ok((input, ClientMessage::Join(chan))) } -fn client_message_mode(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_mode(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("MODE ")(input)?; let (input, target) = recipient(input)?; Ok((input, ClientMessage::Mode { target })) } -fn client_message_who(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_who(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("WHO ")(input)?; let (input, target) = recipient(input)?; Ok((input, ClientMessage::Who { target })) } -fn client_message_topic(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_topic(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("TOPIC ")(input)?; let (input, chan) = chan(input)?; - let (input, _) = tag(b" :")(input)?; + let (input, _) = tag(" :")(input)?; let (input, topic) = token(input)?; - let topic = topic.to_vec(); + let topic = topic.into(); Ok((input, ClientMessage::Topic { chan, topic })) } -fn client_message_part(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_part(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("PART ")(input)?; let (input, chan) = chan(input)?; - let (input, _) = tag(b" :")(input)?; + let (input, _) = tag(" :")(input)?; let (input, message) = token(input)?; - let message = message.to_vec(); + let message = message.into(); Ok((input, ClientMessage::Part { chan, message })) } -fn client_message_privmsg(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_privmsg(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("PRIVMSG ")(input)?; let (input, recipient) = recipient(input)?; let (input, _) = tag(" :")(input)?; let (input, body) = token(input)?; - let body = body.to_vec(); + let body = body.into(); Ok((input, ClientMessage::PrivateMessage { recipient, body })) } -fn client_message_quit(input: &[u8]) -> IResult<&[u8], ClientMessage> { +fn client_message_quit(input: &str) -> IResult<&str, ClientMessage> { let (input, _) = tag("QUIT :")(input)?; let (input, reason) = token(input)?; Ok(( input, ClientMessage::Quit { - reason: reason.to_vec(), + reason: reason.into(), }, )) } @@ -203,23 +203,23 @@ pub enum CapabilitySubcommand { End, } -fn capability_subcommand(input: &[u8]) -> IResult<&[u8], CapabilitySubcommand> { +fn capability_subcommand(input: &str) -> IResult<&str, CapabilitySubcommand> { alt((capability_subcommand_ls, capability_subcommand_end))(input) } -fn capability_subcommand_ls(input: &[u8]) -> IResult<&[u8], CapabilitySubcommand> { +fn capability_subcommand_ls(input: &str) -> IResult<&str, CapabilitySubcommand> { let (input, _) = tag("LS ")(input)?; let (input, code) = take(3usize)(input)?; Ok(( input, CapabilitySubcommand::List { - code: code.try_into().unwrap(), + code: code.as_bytes().try_into().unwrap(), }, )) } -fn capability_subcommand_end(input: &[u8]) -> IResult<&[u8], CapabilitySubcommand> { +fn capability_subcommand_end(input: &str) -> IResult<&str, CapabilitySubcommand> { let (input, _) = tag("END")(input)?; Ok((input, CapabilitySubcommand::End)) } @@ -231,7 +231,7 @@ mod test { use super::*; #[test] fn test_client_message_cap_ls() { - let input = b"CAP LS 302"; + let input = "CAP LS 302"; let expected = ClientMessage::Capability { subcommand: CapabilitySubcommand::List { code: *b"302" }, }; @@ -242,7 +242,7 @@ mod test { #[test] fn test_client_message_cap_end() { - let input = b"CAP END"; + let input = "CAP END"; let expected = ClientMessage::Capability { subcommand: CapabilitySubcommand::End, }; @@ -253,9 +253,9 @@ mod test { #[test] fn test_client_message_ping() { - let input = b"PING 1337"; + let input = "PING 1337"; let expected = ClientMessage::Ping { - token: b"1337".to_vec(), + token: "1337".into(), }; let result = client_message(input); @@ -263,9 +263,9 @@ mod test { } #[test] fn test_client_message_pong() { - let input = b"PONG 1337"; + let input = "PONG 1337"; let expected = ClientMessage::Pong { - token: b"1337".to_vec(), + token: "1337".into(), }; let result = client_message(input); @@ -273,9 +273,9 @@ mod test { } #[test] fn test_client_message_nick() { - let input = b"NICK SomeNick"; + let input = "NICK SomeNick"; let expected = ClientMessage::Nick { - nickname: b"SomeNick".to_vec(), + nickname: "SomeNick".into(), }; let result = client_message(input); @@ -283,10 +283,10 @@ mod test { } #[test] fn test_client_message_user() { - let input = b"USER SomeNick 8 * :Real Name"; + let input = "USER SomeNick 8 * :Real Name"; let expected = ClientMessage::User { - username: b"SomeNick".to_vec(), - realname: b"Real Name".to_vec(), + username: "SomeNick".into(), + realname: "Real Name".into(), }; let result = client_message(input); @@ -294,10 +294,10 @@ mod test { } #[test] fn test_client_message_part() { - let input = b"PART #chan :Pokasiki !!!"; + let input = "PART #chan :Pokasiki !!!"; let expected = ClientMessage::Part { - chan: Chan::Global(b"chan".to_vec()), - message: b"Pokasiki !!!".to_vec(), + chan: Chan::Global("chan".into()), + message: "Pokasiki !!!".into(), }; let result = client_message(input); diff --git a/src/protos/irc/mod.rs b/src/protos/irc/mod.rs index f563f56..8b4c571 100644 --- a/src/protos/irc/mod.rs +++ b/src/protos/irc/mod.rs @@ -11,7 +11,7 @@ use nom::{ }; use tokio::io::{AsyncWrite, AsyncWriteExt}; -type ByteVec = Vec; +type ByteVec = Box; /// Single message tag value. #[derive(Clone, Debug, PartialEq, Eq)] @@ -20,48 +20,48 @@ pub struct Tag { value: Option, } -fn receiver(input: &[u8]) -> IResult<&[u8], &[u8]> { - take_while(|i| i != b'\n' && i != b'\r' && i != b' ')(input) +fn receiver(input: &str) -> IResult<&str, &str> { + take_while(|i| i != '\n' && i != '\r' && i != ' ')(input) } -fn token(input: &[u8]) -> IResult<&[u8], &[u8]> { - take_while(|i| i != b'\n' && i != b'\r')(input) +fn token(input: &str) -> IResult<&str, &str> { + take_while(|i| i != '\n' && i != '\r')(input) } #[derive(Clone, Debug, PartialEq, Eq)] pub enum Chan { /// # — network-global channel, available from any server in the network. - Global(ByteVec), + Global(Box), /// & — server-local channel, available only to connections to the same server. Rarely used in practice. - Local(ByteVec), + Local(Box), } impl Chan { pub async fn write_async(&self, writer: &mut (impl AsyncWrite + Unpin)) -> Result<()> { match self { Chan::Global(name) => { writer.write_all(b"#").await?; - writer.write_all(&name).await?; + writer.write_all(name.as_bytes()).await?; } Chan::Local(name) => { writer.write_all(b"&").await?; - writer.write_all(&name).await?; + writer.write_all(name.as_bytes()).await?; } } Ok(()) } } -fn chan(input: &[u8]) -> IResult<&[u8], Chan> { - fn chan_global(input: &[u8]) -> IResult<&[u8], Chan> { +fn chan(input: &str) -> IResult<&str, Chan> { + fn chan_global(input: &str) -> IResult<&str, Chan> { let (input, _) = tag("#")(input)?; let (input, name) = receiver(input)?; - Ok((input, Chan::Global(name.to_vec()))) + Ok((input, Chan::Global(name.into()))) } - fn chan_local(input: &[u8]) -> IResult<&[u8], Chan> { + fn chan_local(input: &str) -> IResult<&str, Chan> { let (input, _) = tag("&")(input)?; let (input, name) = receiver(input)?; - Ok((input, Chan::Local(name.to_vec()))) + Ok((input, Chan::Local(name.into()))) } alt((chan_global, chan_local))(input) @@ -75,22 +75,22 @@ pub enum Recipient { impl Recipient { pub async fn write_async(&self, writer: &mut (impl AsyncWrite + Unpin)) -> Result<()> { match self { - Recipient::Nick(nick) => writer.write_all(&nick).await?, + Recipient::Nick(nick) => writer.write_all(nick.as_bytes()).await?, Recipient::Chan(chan) => chan.write_async(writer).await?, } Ok(()) } } -fn recipient(input: &[u8]) -> IResult<&[u8], Recipient> { - fn recipient_chan(input: &[u8]) -> IResult<&[u8], Recipient> { +fn recipient(input: &str) -> IResult<&str, Recipient> { + fn recipient_chan(input: &str) -> IResult<&str, Recipient> { let (input, chan) = chan(input)?; Ok((input, Recipient::Chan(chan))) } - fn recipient_nick(input: &[u8]) -> IResult<&[u8], Recipient> { + fn recipient_nick(input: &str) -> IResult<&str, Recipient> { let (input, nick) = receiver(input)?; - Ok((input, Recipient::Nick(nick.to_vec()))) + Ok((input, Recipient::Nick(nick.into()))) } alt((recipient_chan, recipient_nick))(input) @@ -105,8 +105,8 @@ mod test { #[test] fn test_chan_global() { - let input = b"#testchan"; - let expected = Chan::Global(b"testchan".to_vec()); + let input = "#testchan"; + let expected = Chan::Global("testchan".into()); let result = chan(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); @@ -116,13 +116,13 @@ mod test { .unwrap() .unwrap(); - assert_eq!(bytes.as_slice(), input); + assert_eq!(bytes.as_slice(), input.as_bytes()); } #[test] fn test_chan_local() { - let input = b"&localchan"; - let expected = Chan::Local(b"localchan".to_vec()); + let input = "&localchan"; + let expected = Chan::Local("localchan".into()); let result = chan(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); @@ -132,13 +132,13 @@ mod test { .unwrap() .unwrap(); - assert_eq!(bytes.as_slice(), input); + assert_eq!(bytes.as_slice(), input.as_bytes()); } #[test] fn test_recipient_user() { - let input = b"User"; - let expected = Recipient::Nick(b"User".to_vec()); + let input = "User"; + let expected = Recipient::Nick("User".into()); let result = recipient(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); @@ -148,6 +148,6 @@ mod test { .unwrap() .unwrap(); - assert_eq!(bytes.as_slice(), input); + assert_eq!(bytes.as_slice(), input.as_bytes()); } } diff --git a/src/protos/irc/server.rs b/src/protos/irc/server.rs index 107d740..4671333 100644 --- a/src/protos/irc/server.rs +++ b/src/protos/irc/server.rs @@ -18,7 +18,7 @@ impl ServerMessage { match &self.sender { Some(ref sender) => { writer.write_all(b":").await?; - writer.write_all(sender.as_slice()).await?; + writer.write_all(sender.as_bytes()).await?; writer.write_all(b" ").await?; } None => {} @@ -29,9 +29,9 @@ impl ServerMessage { } } -pub fn server_message(input: &[u8]) -> IResult<&[u8], ServerMessage> { +pub fn server_message(input: &str) -> IResult<&str, ServerMessage> { let (input, command) = server_message_body(input)?; - let (input, _) = tag(b"\n")(input)?; + let (input, _) = tag("\n")(input)?; let message = ServerMessage { tags: vec![], @@ -143,25 +143,25 @@ impl ServerMessageBody { text, } => { writer.write_all(b"NOTICE ").await?; - writer.write_all(&first_target).await?; + writer.write_all(first_target.as_bytes()).await?; writer.write_all(b" :").await?; - writer.write_all(&text).await?; + writer.write_all(text.as_bytes()).await?; } ServerMessageBody::Ping { token } => { writer.write_all(b"PING ").await?; - writer.write_all(&token).await?; + writer.write_all(token.as_bytes()).await?; } ServerMessageBody::Pong { from, token } => { writer.write_all(b"PONG ").await?; - writer.write_all(&from).await?; + writer.write_all(from.as_bytes()).await?; writer.write_all(b" :").await?; - writer.write_all(&token).await?; + writer.write_all(token.as_bytes()).await?; } ServerMessageBody::PrivateMessage { target, body } => { writer.write_all(b"PRIVMSG ").await?; target.write_async(writer).await?; writer.write_all(b" :").await?; - writer.write_all(&body).await?; + writer.write_all(body.as_bytes()).await?; } ServerMessageBody::Join(chan) => { writer.write_all(b"JOIN ").await?; @@ -173,25 +173,25 @@ impl ServerMessageBody { } ServerMessageBody::Error { reason } => { writer.write_all(b"ERROR :").await?; - writer.write_all(&reason).await?; + writer.write_all(reason.as_bytes()).await?; } ServerMessageBody::N001Welcome { client, text } => { writer.write_all(b"001 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" :").await?; - writer.write_all(text).await?; + writer.write_all(text.as_bytes()).await?; } ServerMessageBody::N002YourHost { client, text } => { writer.write_all(b"002 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" :").await?; - writer.write_all(text).await?; + writer.write_all(text.as_bytes()).await?; } ServerMessageBody::N003Created { client, text } => { writer.write_all(b"003 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" :").await?; - writer.write_all(text).await?; + writer.write_all(text.as_bytes()).await?; } ServerMessageBody::N004MyInfo { client, @@ -199,34 +199,34 @@ impl ServerMessageBody { softname, } => { writer.write_all(b"004 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(&hostname).await?; + writer.write_all(hostname.as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(&softname).await?; + writer.write_all(softname.as_bytes()).await?; writer.write_all(b" r CFILPQbcefgijklmnopqrstvz").await?; // TODO remove hardcoded modes } ServerMessageBody::N005ISupport { client, params } => { writer.write_all(b"005 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(¶ms).await?; + writer.write_all(params.as_bytes()).await?; writer.write_all(b" :are supported by this server").await?; } ServerMessageBody::N221UserModeIs { client, modes } => { writer.write_all(b"221 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(&modes).await?; + writer.write_all(modes.as_bytes()).await?; } ServerMessageBody::N315EndOfWho { client, mask, msg } => { writer.write_all(b"315 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; mask.write_async(writer).await?; writer.write_all(b" :").await?; - writer.write_all(&msg).await?; + writer.write_all(msg.as_bytes()).await?; } ServerMessageBody::N332Topic { client, @@ -234,11 +234,11 @@ impl ServerMessageBody { topic, } => { writer.write_all(b"332 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; chat.write_async(writer).await?; writer.write_all(b" :").await?; - writer.write_all(&topic).await?; + writer.write_all(topic.as_bytes()).await?; } ServerMessageBody::N352WhoReply { client, @@ -251,24 +251,24 @@ impl ServerMessageBody { realname, } => { writer.write_all(b"352 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" * ").await?; - writer.write_all(&username).await?; + writer.write_all(username.as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(&host).await?; + writer.write_all(host.as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(&server).await?; + writer.write_all(server.as_bytes()).await?; writer.write_all(b" ").await?; match flags { AwayStatus::Here => writer.write_all(b"H").await?, AwayStatus::Gone => writer.write_all(b"G").await?, } writer.write_all(b" ").await?; - writer.write_all(&nickname).await?; + writer.write_all(nickname.as_bytes()).await?; writer.write_all(b" :").await?; writer.write_all(hops.to_string().as_bytes()).await?; writer.write_all(b" ").await?; - writer.write_all(&realname).await?; + writer.write_all(realname.as_bytes()).await?; } ServerMessageBody::N353NamesReply { client, @@ -276,15 +276,15 @@ impl ServerMessageBody { members, } => { writer.write_all(b"353 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" = ").await?; chan.write_async(writer).await?; writer.write_all(b" :").await?; - writer.write_all(&members).await?; + writer.write_all(members.as_bytes()).await?; } ServerMessageBody::N366NamesReplyEnd { client, chan } => { writer.write_all(b"366 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; chan.write_async(writer).await?; writer.write_all(b" :End of /NAMES list").await?; @@ -295,11 +295,11 @@ impl ServerMessageBody { message, } => { writer.write_all(b"474 ").await?; - writer.write_all(&client).await?; + writer.write_all(client.as_bytes()).await?; writer.write_all(b" ").await?; chan.write_async(writer).await?; writer.write_all(b" :").await?; - writer.write_all(&message).await?; + writer.write_all(message.as_bytes()).await?; } } Ok(()) @@ -312,7 +312,7 @@ pub enum AwayStatus { Gone, } -fn server_message_body(input: &[u8]) -> IResult<&[u8], ServerMessageBody> { +fn server_message_body(input: &str) -> IResult<&str, ServerMessageBody> { alt(( server_message_body_notice, server_message_body_ping, @@ -320,14 +320,14 @@ fn server_message_body(input: &[u8]) -> IResult<&[u8], ServerMessageBody> { ))(input) } -fn server_message_body_notice(input: &[u8]) -> IResult<&[u8], ServerMessageBody> { +fn server_message_body_notice(input: &str) -> IResult<&str, ServerMessageBody> { let (input, _) = tag("NOTICE ")(input)?; let (input, first_target) = receiver(input)?; let (input, _) = tag(" :")(input)?; let (input, text) = token(input)?; - let first_target = first_target.to_owned(); - let text = text.to_owned(); + let first_target = first_target.into(); + let text = text.into(); Ok(( input, ServerMessageBody::Notice { @@ -338,19 +338,19 @@ fn server_message_body_notice(input: &[u8]) -> IResult<&[u8], ServerMessageBody> )) } -fn server_message_body_ping(input: &[u8]) -> IResult<&[u8], ServerMessageBody> { +fn server_message_body_ping(input: &str) -> IResult<&str, ServerMessageBody> { let (input, _) = tag("PING ")(input)?; let (input, token) = token(input)?; Ok(( input, ServerMessageBody::Ping { - token: token.to_owned(), + token: token.into(), }, )) } -fn server_message_body_pong(input: &[u8]) -> IResult<&[u8], ServerMessageBody> { +fn server_message_body_pong(input: &str) -> IResult<&str, ServerMessageBody> { let (input, _) = tag("PONG ")(input)?; let (input, from) = receiver(input)?; let (input, _) = tag(" :")(input)?; @@ -359,8 +359,8 @@ fn server_message_body_pong(input: &[u8]) -> IResult<&[u8], ServerMessageBody> { Ok(( input, ServerMessageBody::Pong { - from: from.to_owned(), - token: token.to_owned(), + from: from.into(), + token: token.into(), }, )) } @@ -374,14 +374,14 @@ mod test { #[test] fn test_server_message_notice() { - let input = b"NOTICE * :*** Looking up your hostname...\n"; + let input = "NOTICE * :*** Looking up your hostname...\n"; let expected = ServerMessage { tags: vec![], sender: None, body: ServerMessageBody::Notice { - first_target: b"*".to_vec(), + first_target: "*".into(), rest_targets: vec![], - text: b"*** Looking up your hostname...".to_vec(), + text: "*** Looking up your hostname...".into(), }, }; @@ -392,18 +392,18 @@ mod test { sync_future(expected.write_async(&mut bytes)) .unwrap() .unwrap(); - assert_eq!(bytes, input); + assert_eq!(bytes, input.as_bytes()); } #[test] fn test_server_message_pong() { - let input = b"PONG server.example :LAG004911\n"; + let input = "PONG server.example :LAG004911\n"; let expected = ServerMessage { tags: vec![], sender: None, body: ServerMessageBody::Pong { - from: b"server.example".to_vec(), - token: b"LAG004911".to_vec(), + from: "server.example".into(), + token: "LAG004911".into(), }, }; @@ -414,6 +414,6 @@ mod test { sync_future(expected.write_async(&mut bytes)) .unwrap() .unwrap(); - assert_eq!(bytes, input); + assert_eq!(bytes, input.as_bytes()); } } diff --git a/src/protos/xmpp/bind.rs b/src/protos/xmpp/bind.rs index 201fc61..a2b1d7f 100644 --- a/src/protos/xmpp/bind.rs +++ b/src/protos/xmpp/bind.rs @@ -12,7 +12,7 @@ pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-bind"; // TODO remove `pub` in newtypes, introduce validation #[derive(PartialEq, Eq, Debug, Clone)] -pub struct Name(pub String); +pub struct Name(pub Box); #[derive(PartialEq, Eq, Debug, Clone)] pub struct Server(pub String); @@ -49,7 +49,7 @@ impl Jid { .captures(i) .ok_or(ffail!("Incorrectly format jid: {i}"))?; - let name = m.get(2).map(|name| Name(name.as_str().to_string())); + let name = m.get(2).map(|name| Name(name.as_str().into())); let server = m.get(3).unwrap(); let server = Server(server.as_str().to_string()); let resource = m diff --git a/src/protos/xmpp/client.rs b/src/protos/xmpp/client.rs index 1b019a9..02df4b7 100644 --- a/src/protos/xmpp/client.rs +++ b/src/protos/xmpp/client.rs @@ -613,7 +613,7 @@ mod tests { from: None, id: Some("aacea".to_string()), to: Some(Jid { - name: Some(Name("nikita".to_owned())), + name: Some(Name("nikita".into())), server: Server("vlnv.dev".to_owned()), resource: None }),