use std::fmt; use std::str::{from_utf8, from_utf8_unchecked}; #[derive(Copy,Clone,Debug,Eq,PartialEq,Ord,PartialOrd)] pub enum IrcCommand<'a> { Stringy(Stringy<'a>), Numeric(Numeric<'a>) } #[derive(Copy,Clone,Debug,Eq,PartialEq,Ord,PartialOrd)] pub struct Stringy<'a>(&'a [u8]); #[derive(Copy,Clone,Debug,Eq,PartialEq,Ord,PartialOrd)] pub struct Numeric<'a>(u16, &'a [u8; 3]); pub trait IrcCommandCall { fn get_command<'a>(&'a self) -> IrcCommand<'a>; } impl<'a> fmt::Display for Stringy<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut i = 0; let l = self.0.len(); let v = self.0; while i < l { let st = from_utf8(&v[i..]); if let Ok(s) = st { write!(f, "{}", s)?; } else { let err = st.err().unwrap(); write!(f, "{}", unsafe { from_utf8_unchecked(&v[i..][..err.valid_up_to()])})?; write!(f, "\u{FFFD}")?; match err.error_len() { None => i = l, Some(len) => i = i + err.valid_up_to() + len } } } Ok(()) } } impl<'a> IrcCommand<'a> { pub fn new(cmd: &'a [u8]) -> IrcCommand<'a> { if cmd.len() == 3 && match (cmd[0], cmd[1], cmd[2]) { (b'0'...b'9', b'0'...b'9', b'0'...b'9') => true, _ => false } { IrcCommand::Numeric(Numeric(from_utf8_unchecked(cmd).parse().unwrap(), array_ref![cmd,0,3])) } else { IrcCommand::Stringy(Stringy(cmd)) } } }