Add random stuff
This commit is contained in:
commit
767331aa3d
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
|
/recovered_revisions/
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "uirc"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["SoniEx2 <endermoneymod@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
arrayref = "0.3.4"
|
||||||
|
matches = "0.1.6"
|
|
@ -0,0 +1,175 @@
|
||||||
|
use std::fmt;
|
||||||
|
use std::str::{from_utf8, from_utf8_unchecked};
|
||||||
|
|
||||||
|
/// An IRC command
|
||||||
|
#[derive(Copy,Clone,Debug,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
|
pub enum IrcCommand<'a> {
|
||||||
|
Stringy(Stringy<'a>),
|
||||||
|
Numeric(Numeric<'a>)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A stringy IRC command
|
||||||
|
#[derive(Copy,Clone,Debug,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
|
pub struct Stringy<'a>(&'a [u8]);
|
||||||
|
|
||||||
|
/// A numeric IRC command.
|
||||||
|
#[derive(Copy,Clone,Debug,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
|
pub struct Numeric<'a>(u16, &'a [u8; 3]);
|
||||||
|
|
||||||
|
/// A full IRC command line.
|
||||||
|
pub trait IrcCommandLine {
|
||||||
|
fn get_command<'a>(&'a self) -> IrcCommand<'a>;
|
||||||
|
|
||||||
|
/// Experimental. Do not use.
|
||||||
|
fn get_argument<'a>(&'a self, arg: usize) -> &'a [u8];
|
||||||
|
/// Experimental. Do not use.
|
||||||
|
fn get_argument_count(&self) -> usize;
|
||||||
|
/// Experimental. Do not use.
|
||||||
|
fn get_source<'a>(&'a self) -> &'a [u8];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Stringy<'a> {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(cmd: &'a [u8]) -> Option<Stringy<'a>> {
|
||||||
|
if cmd.len() == 3 && matches!((cmd[0], cmd[1], cmd[2]), (b'0'...b'9', b'0'...b'9', b'0'...b'9')) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Self::new_unchecked(cmd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn new_unchecked(cmd: &'a [u8]) -> Stringy<'a> {
|
||||||
|
Stringy(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_bytes(&self) -> &'a [u8] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Numeric<'a> {
|
||||||
|
/// Creates a new numeric from the given bytes. Returns None if the given bytes aren't a valid
|
||||||
|
/// numeric.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use uirc::command::Numeric;
|
||||||
|
///
|
||||||
|
/// match Numeric::new(b"005") {
|
||||||
|
/// Some(numeric) => println!("Numeric: {}", numeric),
|
||||||
|
/// None => println!("Not a numeric!"),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new numeric from the given bytes. Returns None if the given bytes aren't a valid
|
||||||
|
/// numeric.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use uirc::command::Numeric;
|
||||||
|
///
|
||||||
|
/// match Numeric::new_from_slice(b"005") {
|
||||||
|
/// Some(numeric) => println!("Numeric: {}", numeric),
|
||||||
|
/// None => println!("Not a numeric!"),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn new_from_slice(cmd: &'a [u8]) -> Option<Numeric<'a>> {
|
||||||
|
if cmd.len() == 3 {
|
||||||
|
// TODO switch to TryFrom/TryInto once those are stable. (rust-lang/rust#33417)
|
||||||
|
Self::new(array_ref![cmd, 0, 3])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not unsafe, but may produce unexpected results
|
||||||
|
// keep this private (for now)
|
||||||
|
#[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.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use uirc::command::Numeric;
|
||||||
|
///
|
||||||
|
/// let numeric = Numeric::new(b"005").unwrap();
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```rust
|
||||||
|
/// use uirc::command::Numeric;
|
||||||
|
/// use std::io::Write;
|
||||||
|
///
|
||||||
|
/// let mut client = Vec::new();
|
||||||
|
/// let numeric = Numeric::new(b"005").unwrap();
|
||||||
|
/// let bytes = numeric.get_bytes();
|
||||||
|
/// client.write_all(bytes).unwrap();
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn get_bytes(&self) -> &'a [u8; 3] {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IrcCommand<'a> {
|
||||||
|
pub fn new(cmd: &'a [u8]) -> IrcCommand<'a> {
|
||||||
|
if let Some(numeric) = Numeric::new_from_slice(cmd) {
|
||||||
|
IrcCommand::Numeric(numeric)
|
||||||
|
} else {
|
||||||
|
IrcCommand::Stringy(Stringy::new(cmd).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)?;
|
||||||
|
break;
|
||||||
|
} 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
// What was I gonna put here?
|
||||||
|
//
|
||||||
|
// I didn't manage to recover this file from the depths of /dev/sdb1, so I don't know what it was
|
||||||
|
// for.
|
|
@ -0,0 +1,10 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate arrayref;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate matches;
|
||||||
|
|
||||||
|
pub mod command;
|
||||||
|
|
||||||
|
pub mod commands;
|
||||||
|
|
||||||
|
pub mod simple;
|
|
@ -0,0 +1,38 @@
|
||||||
|
use command::{IrcCommand, IrcCommandLine, Numeric, Stringy};
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
pub struct SimpleIrcCommand {
|
||||||
|
command: Vec<u8>,
|
||||||
|
arguments: (Vec<Range<usize>>, Vec<u8>),
|
||||||
|
source: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrcCommandLine for SimpleIrcCommand {
|
||||||
|
fn get_command<'a>(&'a self) -> IrcCommand<'a> {
|
||||||
|
IrcCommand::new(&self.command)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_argument<'a>(&'a self, arg: usize) -> &'a [u8] {
|
||||||
|
&self.arguments.1[self.arguments.0[arg].clone()] // awful API there, rust.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_argument_count(&self) -> usize {
|
||||||
|
self.arguments.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_source<'a>(&'a self) -> &'a [u8] {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoIrcConnection;
|
||||||
|
|
||||||
|
impl NoIrcConnection {
|
||||||
|
pub fn read_command<R: Read>(reader: R) -> io::Result<SimpleIrcCommand> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue