diff --git a/src/lib.rs b/src/lib.rs index 0ead25d..91830fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,9 @@ extern crate time; extern crate encoding; extern crate rustc_serialize; +extern crate tokio_core; +extern crate tokio_proto; +extern crate tokio_service; pub mod client; pub mod proto; diff --git a/src/proto/irc.rs b/src/proto/irc.rs new file mode 100644 index 0000000..7b21599 --- /dev/null +++ b/src/proto/irc.rs @@ -0,0 +1 @@ +//! Implementation of IRC protocol for Tokio. diff --git a/src/proto/line.rs b/src/proto/line.rs new file mode 100644 index 0000000..5a1f575 --- /dev/null +++ b/src/proto/line.rs @@ -0,0 +1,53 @@ +//! Implementation of line-based codec for Tokio. + +use std::io; +use std::io::prelude::*; +use encoding::{DecoderTrap, EncoderTrap, Encoding}; +use tokio_core::io::{Codec, EasyBuf}; + +/// A line-based codec parameterized by an encoding. +pub struct LineCodec { + encoding: E, +} + +impl Codec for LineCodec where E: Encoding { + type In = String; + type Out = String; + + fn decode(&mut self, buf: &mut EasyBuf) -> io::Result> { + if let Some(n) = buf.as_ref().iter().position(|b| *b == b'\n') { + // Remove the next frame from the buffer. + let line = buf.drain_to(n); + + // Remove the new-line from the buffer. + buf.drain_to(1); + + // Decode the line using the codec's encoding. + match self.encoding.decode(line.as_ref(), DecoderTrap::Replace) { + Ok(data) => Ok(Some(data)), + Err(data) => Err(io::Error::new( + io::ErrorKind::InvalidInput, + &format!("Failed to decode {} as {}.", data, self.encoding.name())[..] + )) + } + } else { + Ok(None) + } + } + + fn encode(&mut self, msg: String, buf: &mut Vec) -> io::Result<()> { + // Encode the message using the codec's encoding. + let data = try!(self.encoding.encode(&msg, EncoderTrap::Replace).map_err(|data| { + io::Error::new( + io::ErrorKind::InvalidInput, + &format!("Failed to encode {} as {}.", data, self.encoding.name())[..] + ) + })); + + // Write the encoded message to the output buffer. + try!(buf.write_all(&data)); + + // Flush the output buffer. + buf.flush() + } +} diff --git a/src/proto/mod.rs b/src/proto/mod.rs index d592bf2..5a7b7a1 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -2,5 +2,7 @@ pub mod caps; pub mod command; +pub mod irc; +pub mod line; pub mod message; pub mod response;