thingy/recovered_revisions/src/command_rs/file.331391590746

114 lines
3.1 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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> fmt::Display for Numeric<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<'a> Stringy<'a> {
}
impl<'a> Numeric<'a> {
pub fn new(cmd: &'a [u8; 3]) -> Option<Numeric<'a>> {
match (cmd[0], cmd[1], cmd[2]) {
(b'0'...b'9', b'0'...b'9', b'0'...b'9') => Some(Numeric::new_unchecked(cmd)),
_ => None
}
}
// not unsafe, but may produce unexpected results
// keep this private
#[inline]
fn new_unchecked(cmd: &'a [u8; 3]) -> Numeric<'a> {
Numeric(cmd.iter().map(|x| (x-b'0') as u16).fold(0, |x,y| x*10+y), cmd)
}
/// Returns the numeric as a number, e.g. for processing in code.
///
/// # Example
/// ```
/// use uirc::command::Numeric;
///
/// if let Some(numeric) = Numeric::new(b"005") {
/// match numeric.get_numeric() {
/// 005 => println!("got an ISUPPORT!"),
/// _ => println!("got something else!"),
/// }
/// }
/// ```
#[inline]
pub fn get_numeric(&self) -> u16 {
self.0
}
/// Returns the numeric as bytes, e.g. for writing to a stream.
///
/// # Example
/// ```rust,ignore
/// use uirc::command::Numeric;
///
/// let mut client = Vec::new();
/// if let Some(numeric) = Numeric::new(b"005") {
/// let bytes = numeric.get_bytes();
/// write!(client, bytes);
/// }
/// ```
#[inline]
pub fn get_bytes(&self) -> &'a [u8; 3] {
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_unchecked(array_ref![cmd,0,3]))
} else {
IrcCommand::Stringy(Stringy(cmd))
}
}
}