Add a simple PRIVMSG test
Diff
titanirc-codec/src/lib.rs | 3 +++
titanirc-codec/src/wire.rs | 23 +++++++++++------------
titanirc-server/src/main.rs | 3 +++
titanirc-server/src/server.rs | 2 +-
titanirc-server/src/session.rs | 2 +-
titanirc-types/src/lib.rs | 31 +++++++++++++++++++++++++++----
titanirc-types/src/primitives.rs | 20 +++++++-------------
7 files changed, 53 insertions(+), 31 deletions(-)
@@ -1,3 +1,6 @@
#![deny(clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
mod wire;
pub use crate::wire::Decoder;
@@ -11,19 +11,18 @@ impl FrameDecoder for Decoder {
type Error = std::io::Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
let length = match find_crlf(src) {
Some(len) => len,
None => {
if src.len() > MAX_LENGTH {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Frame of length {} is too large.", src.len()),
));
}
return Ok(None);
let length = if let Some(len) = find_crlf(src) {
len
} else {
if src.len() > MAX_LENGTH {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Frame of length {} is too large.", src.len()),
));
}
return Ok(None);
};
let bytes = src.copy_to_bytes(length + 1);
@@ -1,3 +1,6 @@
#![deny(clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
mod error;
mod server;
mod session;
@@ -23,7 +23,7 @@ impl Handler<Connection> for Server {
println!("Accepted connection from {}", remote);
Session::create(move |ctx| {
let (read, write) = tokio::io::split(stream);
let (read, _write) = tokio::io::split(stream);
Session::add_stream(FramedRead::new(read, titanirc_codec::Decoder), ctx);
Session {}
});
@@ -9,7 +9,7 @@ impl Actor for Session {
impl StreamHandler<Result<Command, std::io::Error>> for Session {
fn handle(&mut self, cmd: Result<Command, std::io::Error>, ctx: &mut Self::Context) {
fn handle(&mut self, cmd: Result<Command, std::io::Error>, _ctx: &mut Self::Context) {
match cmd {
Ok(cmd) => println!("cmd: {:?}", cmd),
Err(e) => eprintln!("error decoding: {}", e),
@@ -1,3 +1,6 @@
#![deny(clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
mod primitives;
pub use crate::primitives::*;
@@ -16,14 +19,12 @@ macro_rules! define_commands {
$([<$name:camel>]([<$name:camel Command>])),*
}
$(const [<$name _BYTES>]: &[u8] = stringify!($name).as_bytes();)*
impl Command {
pub fn parse(input: &[u8]) -> Result<Option<Self>, nom::Err<nom::error::Error<&[u8]>>> {
let (rest, kind) = nom::bytes::complete::take_till(|c| c == b' ')(input)?;
$(const [<$name _BYTES>]: &[u8] = stringify!($name).as_bytes();)*
eprintln!("kind: {:?}", std::str::from_utf8(kind));
match kind {
$([<$name _BYTES>] => Ok(Some(Self::[<$name:camel>]([<$name:camel Command>]::parse(rest)?)))),*,
_ => Ok(None)
@@ -38,6 +39,7 @@ macro_rules! define_commands {
}
impl [<$name:camel Command>] {
#[allow(unused_variables)]
pub fn parse(rest: &[u8]) -> Result<Self, nom::Err<nom::error::Error<&[u8]>>> {
$(
$(
@@ -72,3 +74,24 @@ define_commands! {
PRIVMSG(Receiver, Message),
}
#[cfg(test)]
mod tests {
use super::Command;
#[test]
fn parse_empty() {
assert!(matches!(Command::parse(b""), Ok(None)));
}
#[test]
fn parse_privmsg() {
assert!(matches!(
Command::parse(b"PRIVMSG foo :baz"),
Ok(Some(Command::Privmsg(super::PrivmsgCommand {
receiver: super::Receiver::User(super::Nick(nick)),
message: super::Message(msg),
}))) if nick == "foo" && msg == ":baz"
))
}
}
@@ -23,33 +23,27 @@ macro_rules! standard_string_parser {
}
#[derive(Debug)]
pub struct Username(String);
pub struct Username(pub(crate) String);
standard_string_parser!(Username);
#[derive(Debug)]
pub struct HostName(String);
pub struct HostName(pub(crate) String);
standard_string_parser!(HostName);
#[derive(Debug)]
pub struct ServerName(String);
pub struct ServerName(pub(crate) String);
standard_string_parser!(ServerName);
#[derive(Debug)]
pub struct RealName(String);
pub struct RealName(pub(crate) String);
standard_string_parser!(RealName);
#[derive(Debug)]
pub struct Nick(String);
pub struct Nick(pub(crate) String);
standard_string_parser!(Nick);
#[derive(Debug)]
pub struct Channel(String);
pub struct Channel(pub(crate) String);
standard_string_parser!(Channel);
#[derive(Debug)]
@@ -73,7 +67,7 @@ impl PrimitiveParser for Receiver {
}
#[derive(Debug)]
pub struct Message(String);
pub struct Message(pub(crate) String);
impl PrimitiveParser for Message {
fn parse(bytes: &[u8]) -> IResult<&[u8], Self> {