diff options
Diffstat (limited to 'vndbapi-msg/src/msg.rs')
-rw-r--r-- | vndbapi-msg/src/msg.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/vndbapi-msg/src/msg.rs b/vndbapi-msg/src/msg.rs new file mode 100644 index 0000000..ead8ac0 --- /dev/null +++ b/vndbapi-msg/src/msg.rs @@ -0,0 +1,130 @@ +use std::fmt; +use serde_json::Value; + +use parser::{parse_filter,parse_arg,parse_message}; + + +#[derive(Debug,Clone)] +pub enum Arg { + BareString(String), + Json(Value), + Filter(Filter), +} + +#[derive(Debug,Clone)] +pub struct Message { + name: String, + args: Vec<Arg>, +} + + +#[derive(Debug,Clone)] +pub enum Filter { + And(Box<Filter>, Box<Filter>), + Or(Box<Filter>, Box<Filter>), + Expr(String, Op, Value), +} + + +#[derive(Debug,Clone,Copy,PartialEq,Eq)] +pub enum Op { + Eq, + NEq, + Le, + LEq, + Gt, + GEq, + Fuzzy, +} + + +impl Op { + pub fn as_str(self) -> &'static str { + match self { + Op::Eq => "=", + Op::NEq => "!=", + Op::Le => "<", + Op::LEq => "<=", + Op::Gt => ">", + Op::GEq => ">=", + Op::Fuzzy => "~", + } + } +} + + +impl fmt::Display for Op { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.as_str()) + } +} + + +impl fmt::Display for Filter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &Filter::And(ref x, ref y) => write!(f, "({} and {})", x, y), + &Filter::Or(ref x, ref y) => write!(f, "({} or {})", x, y), + &Filter::Expr(ref n, o, ref v) => write!(f, "({} {} {})", n, o, v), + } + } +} + + +impl fmt::Display for Arg { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &Arg::BareString(ref x) => f.write_str(&x), + &Arg::Json(ref x) => write!(f, "{}", x), + &Arg::Filter(ref x) => write!(f, "{}", x), + } + } +} + + +impl fmt::Display for Message { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.name)?; + for a in self.args.iter() { + f.write_str(" ")?; + write!(f, "{}", a)?; + } + Ok(()) + } +} + + +impl Filter { + pub fn parse(s: &str) -> Result<(Filter, &str), &'static str> { + parse_filter(s) + } +} + + +impl Arg { + pub fn parse(s: &str) -> Result<(Arg, &str), &'static str> { + parse_arg(s) + } +} + + +impl Message { + pub fn parse(s: &str) -> Result<Message, &'static str> { + parse_message(s) + } + + pub fn new(name: &str) -> Result<Message, &'static str> { + if name.contains(|c| !(c >= 'a' && c <= 'z')) { + return Err("Invalid message name") + } + Ok(Message{name: name.to_string(), args: Vec::new()}) + } + + pub fn push_arg(mut self, arg: Arg) -> Message { self.args.push(arg); self } + pub fn push_bare (self, arg: &str ) -> Message { self.push_arg(Arg::BareString(arg.to_string())) } + pub fn push_json (self, arg: Value ) -> Message { self.push_arg(Arg::Json(arg)) } + pub fn push_filter(self, arg: Filter) -> Message { self.push_arg(Arg::Filter(arg)) } + + pub fn name(&self) -> &str { &self.name } + pub fn args(&self) -> &[Arg] { &self.args } +} |