use super::*; /// Client-to-server command. #[derive(Clone, Debug, PartialEq, Eq)] pub enum ClientMessage { /// CAP. Capability-related commands. Capability { subcommand: CapabilitySubcommand, }, /// PING Ping { token: ByteVec, }, Pong { token: ByteVec, }, } pub fn client_message(input: &[u8]) -> IResult<&[u8], ClientMessage> { alt(( client_message_capability, client_message_ping, client_message_pong, ))(input) } fn client_message_capability(input: &[u8]) -> IResult<&[u8], 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> { let (input, _) = tag("PING ")(input)?; let (input, token) = token(input)?; Ok(( input, ClientMessage::Ping { token: token.to_owned(), }, )) } fn client_message_pong(input: &[u8]) -> IResult<&[u8], ClientMessage> { let (input, _) = tag("PONG ")(input)?; let (input, token) = token(input)?; Ok(( input, ClientMessage::Pong { token: token.to_owned(), }, )) } #[derive(Clone, Debug, PartialEq, Eq)] pub enum CapabilitySubcommand { /// CAP LS {code} List { code: [u8; 3] }, /// CAP END End, } fn capability_subcommand(input: &[u8]) -> IResult<&[u8], CapabilitySubcommand> { alt((capability_subcommand_ls, capability_subcommand_end))(input) } fn capability_subcommand_ls(input: &[u8]) -> IResult<&[u8], CapabilitySubcommand> { let (input, _) = tag("LS ")(input)?; let (input, code) = take(3usize)(input)?; Ok(( input, CapabilitySubcommand::List { code: code.try_into().unwrap(), }, )) } fn capability_subcommand_end(input: &[u8]) -> IResult<&[u8], CapabilitySubcommand> { let (input, _) = tag("END")(input)?; Ok((input, CapabilitySubcommand::End)) } #[cfg(test)] mod test { use assert_matches::*; use super::*; #[test] fn test_client_message_cap_ls() { let input = b"CAP LS 302"; let expected = ClientMessage::Capability { subcommand: CapabilitySubcommand::List { code: *b"302" }, }; let result = client_message(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); } #[test] fn test_client_message_cap_end() { let input = b"CAP END"; let expected = ClientMessage::Capability { subcommand: CapabilitySubcommand::End, }; let result = client_message(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); } #[test] fn test_client_message_ping() { let input = b"PING 1337"; let expected = ClientMessage::Ping { token: b"1337".to_vec(), }; let result = client_message(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); } #[test] fn test_client_message_pong() { let input = b"PONG 1337"; let expected = ClientMessage::Pong { token: b"1337".to_vec(), }; let result = client_message(input); assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result)); } }