From fe905274cdfc6b7071e166e1edf2948c3734d25d Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Mon, 1 Feb 2021 01:55:55 +0000 Subject: [PATCH] Add some docs for titanirc_types --- titanirc-types/src/lib.rs | 20 ++++++++++++++------ titanirc-types/src/primitives.rs | 2 ++ titanirc-types/src/replies.rs | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/titanirc-types/src/lib.rs b/titanirc-types/src/lib.rs index 044d762..ad5b569 100644 --- a/titanirc-types/src/lib.rs +++ b/titanirc-types/src/lib.rs @@ -29,6 +29,9 @@ macro_rules! define_commands { ),* $(,)? ) => { paste::paste! { + /// All the commands that can be ran by a client, also provides a `Display` + /// implementation that serialises the command for sending over the wire, + /// ie. for forwarding. #[derive(Debug)] pub enum Command<'a> { $([<$name:camel>]([<$name:camel Command>]<'a>)),* @@ -37,15 +40,16 @@ macro_rules! define_commands { $(const [<$name _BYTES>]: &[u8] = stringify!($name).as_bytes();)* impl Command<'_> { + /// Parses a command from the wire, returning an `Err` if the command was unparsable or + /// `Ok(None)` if the command was unrecognsied. The given `Bytes` should have the CRLF + /// stripped. pub fn parse(input: Bytes) -> Result, nom::Err>> { - let input = BytesWrapper::from(input); + let mut input = BytesWrapper::from(input); // skip the optional source at the start of the message - let input = if let Ok((input, _)) = parse_optional_source(input.clone()) { - input - } else { - input - }; + if let Ok((input_source_stripped, _)) = parse_optional_source(input.clone()) { + input = input_source_stripped; + } let (params, command) = take_till(|c| c == b' ')(input)?; @@ -56,6 +60,7 @@ macro_rules! define_commands { } } + /// Serialises the command for sending over the wire. impl std::fmt::Display for Command<'_> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -72,6 +77,7 @@ macro_rules! define_commands { } impl [<$name:camel Command>]<'_> { + /// Parses the command's arguments, with each parameter separated by a space. #[allow(unused_variables)] pub fn parse(rest: BytesWrapper) -> Result>> { $( @@ -88,6 +94,8 @@ macro_rules! define_commands { } } + /// Serialises the command's arguments for sending over the wire, joining + /// all the arguments separating them with a space. impl std::fmt::Display for [<$name:camel Command>]<'_> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fmt.write_str(stringify!($name))?; diff --git a/titanirc-types/src/primitives.rs b/titanirc-types/src/primitives.rs index e4f9341..40490d1 100644 --- a/titanirc-types/src/primitives.rs +++ b/titanirc-types/src/primitives.rs @@ -18,6 +18,8 @@ pub trait PrimitiveParser { Self: Sized; } +/// A `Cow`-like implementation where `Owned` is a `bytes::Bytes` and `Borrowed` +/// is `&[u8]`. #[derive(Debug, From)] pub enum BytesCow<'a> { Owned(Bytes), diff --git a/titanirc-types/src/replies.rs b/titanirc-types/src/replies.rs index e680b67..b11eb08 100644 --- a/titanirc-types/src/replies.rs +++ b/titanirc-types/src/replies.rs @@ -3,21 +3,37 @@ use crate::{primitives::*, Command}; use std::fmt::Write; +/// The origin of a message that's about to be returned to the client. #[derive(Debug)] pub enum Source<'a> { User(Nick<'a>), // change Nick to whatever type nick!user@netmask is.. Server, } +impl<'a> From> for Source<'a> { + fn from(other: Nick<'a>) -> Self { + Self::User(other) + } +} + +/// A message to be sent to the client over the wire. #[derive(Debug, derive_more::From)] pub enum ServerMessage<'a> { + /// A `RPL_*`/`ERR_*` type from the IRC spec. Reply(Reply<'a>), + /// Normally a 'forwarded' message, ie. a `VERSION` for another client or + /// a `PRIVMSG`. Command(Source<'a>, Command<'a>), // change Nick to whatever type nick!user@netmask is.. + /// A server ping to the client. Ping, + /// A server pong to the client. Pong, } impl ServerMessage<'_> { + /// Writes out this `ServerMessage` to `dst`, in the expected format for the wire. + /// + /// This function omits the CRLF from the end of the line. pub fn write(self, server_name: &str, client_username: &str, dst: &mut bytes::BytesMut) { match self { Self::Reply(reply) => write!( @@ -48,6 +64,7 @@ macro_rules! define_replies { $name:ident$(($($arg:ident$(<$($gen:tt),+>)?),*))? = $num:expr $(=> $msg:expr)? ),* $(,)? ) => { + /// A `RPL_*` or `ERR_*` type as defined in the IRC spec. #[derive(Debug)] #[allow(clippy::pub_enum_variant_names)] pub enum Reply<'a> { @@ -56,6 +73,7 @@ macro_rules! define_replies { )* } + /// Outputs the `RPL_*`/`ERR_*` type for the wire as defined in the IRC spec. impl std::fmt::Display for Reply<'_> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { paste::paste! { @@ -67,6 +85,7 @@ macro_rules! define_replies { } impl Reply<'_> { + /// The numeric code for this reply kind. #[must_use] pub fn code(&self) -> &'static str { paste::paste! { -- libgit2 1.7.2