67 lines
2.0 KiB
Plaintext
67 lines
2.0 KiB
Plaintext
|
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]);
|
|||
|
|
|||
|
impl<'a> Numeric<'a> {
|
|||
|
// not unsafe, but may produce unexpected results
|
|||
|
// keep this private
|
|||
|
fn new(cmd: &'a [u8; 3]) -> Numeric<'a> {
|
|||
|
Numeric(cmd.iter().map(|x| (x-b'0') as u16).fold(0, |x,y| x*10+y), cmd)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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> fmt::Display for Numeric<'a> {
|
|||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|||
|
write!(f, "{}", unsafe { from_utf8_unchecked(self.1) })
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
impl<'a> IrcCommand<'a> {
|
|||
|
pub fn new(cmd: &'a [u8]) -> IrcCommand<'a> {
|
|||
|
if cmd.len() == 3 && matches!((cmd[0], cmd[1], cmd[2]), (b'0'...b'9', b'0'...b'9', b'0'...b'9')) {
|
|||
|
// TODO switch to TryFrom/TryInto once those are stable. (rust-lang/rust#33417)
|
|||
|
IrcCommand::Numeric(Numeric::new(array_ref![cmd,0,3]))
|
|||
|
} else {
|
|||
|
IrcCommand::Stringy(Stringy(cmd))
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|