summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2017-03-04 11:12:31 +0100
committerYorhel <git@yorhel.nl>2017-03-04 11:12:31 +0100
commit634d0ea29755da9047014f94a04e445646e49bfc (patch)
tree33dd16e08feaf4f56b5948509aa9cfd27366e35b
parentbea3ab5e55acf1da0862c668b73ff4121dd17f39 (diff)
Some old outstanding changes
-rw-r--r--Cargo.toml4
-rw-r--r--src/conn.rs2
-rw-r--r--src/msg.rs24
-rw-r--r--src/parser.rs84
4 files changed, 68 insertions, 46 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 5faf708..a7390a2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
-name = "vndb"
+name = "vndbapi"
version = "0.1.0"
-authors = ["Yorhel <git@yorhel.nl>"]
+authors = ["Yorhel <projects@yorhel.nl>"]
[dependencies]
rustls = "0.5.3"
diff --git a/src/conn.rs b/src/conn.rs
index 84ebc42..a642a59 100644
--- a/src/conn.rs
+++ b/src/conn.rs
@@ -87,6 +87,8 @@ impl Connection {
Ok(m)
}
+ // WARNING: This method should not be called when there are still outstanding commands.
+ // (Might as well get rid of this convenient method to prevent that scenario?)
pub fn cmd(&mut self, cmd: &Message) -> Result<Message, Box<Error>> {
self.send(cmd);
self.recv()
diff --git a/src/msg.rs b/src/msg.rs
index e1c5528..ead8ac0 100644
--- a/src/msg.rs
+++ b/src/msg.rs
@@ -1,7 +1,7 @@
use std::fmt;
use serde_json::Value;
-use parser::{parse_filter,parse_message};
+use parser::{parse_filter,parse_arg,parse_message};
#[derive(Debug,Clone)]
@@ -101,12 +101,30 @@ impl Filter {
}
+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: String, args: Vec<Arg>) -> Message {
- Message{name: name, args: args}
+ 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 }
}
diff --git a/src/parser.rs b/src/parser.rs
index 03b288b..0644e45 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -22,7 +22,6 @@ fn parse_json(s: &str) -> Result<(Value, &str)> {
fn is_ws(c: char) -> bool { c == ' ' || c == '\t' || c == '\r' || c == '\n' }
fn is_filtername(c: char) -> bool { (c >= 'a' && c <= 'z') || c == '_' }
-fn is_msgname(c: char) -> bool { c >= 'a' && c <= 'z' }
fn is_barestr(c: char) -> bool { (c >= 'a' && c <= 'z') || c == '_' || c == ',' }
fn trim_ws(s: &str) -> &str { s.trim_left_matches(is_ws) }
@@ -169,55 +168,58 @@ pub fn parse_filter(s: &str) -> Result<(Filter, &str)> {
}
+pub fn parse_arg(s: &str) -> Result<(Arg, &str)> {
+ let s = trim_ws(s);
+
+ // This match on the first character can be replaced by simply trying parse_filter and
+ // parse_json in sequence; but that results in less than ideal error messages on badly
+ // formatted input.
+ match s.chars().next() {
+ None => return Err("Empty argument"),
+
+ Some('(') => {
+ return parse_filter(s).map(|(v,r)| (Arg::Filter(v), r));
+ },
+
+ Some('[') | Some('{') | Some('"') => {
+ return parse_json(s).map(|(v,r)| (Arg::Json(v), r));
+ },
+
+ Some(_) => {
+ if let Ok((v,r)) = parse_json(s) {
+ return Ok((Arg::Json(v), r));
+
+ } else {
+ let mut splt = s.splitn(2, is_ws);
+ let v = splt.next().unwrap();
+ let rem = splt.next().unwrap_or("");
+
+ if !v.contains(|c| !is_barestr(c)) {
+ return Ok((Arg::BareString(v.to_string()), rem));
+ } else {
+ return Err("Invalid argument")
+ }
+ }
+ },
+ }
+}
+
+
pub fn parse_message(s: &str) -> Result<Message> {
let mut buf = trim_ws(s);
- let mut args = Vec::new();
let mut splt = buf.splitn(2, is_ws);
let name = splt.next().ok_or("Empty message")?;
- if name.contains(|c| !is_msgname(c)) {
- return Err("Invalid message name")
- }
+ let mut msg = Message::new(name)?;
buf = trim_ws(splt.next().unwrap_or(""));
- while let Some(c) = buf.chars().next() {
- // This match on the first character can be replaced by simply trying parse_filter and
- // parse_json in sequence; but that results in less than ideal error messages on badly
- // formatted input.
- match c {
- '(' => {
- let v = parse_filter(buf)?;
- args.push(Arg::Filter(v.0));
- buf = v.1;
- },
- '[' | '{' | '"' => {
- let v = parse_json(buf)?;
- args.push(Arg::Json(v.0));
- buf = v.1;
- },
- _ => {
- if let Ok(v) = parse_json(buf) {
- args.push(Arg::Json(v.0));
- buf = v.1;
-
- } else {
- let mut splt = buf.splitn(2, is_ws);
- let v = splt.next().unwrap();
-
- if !v.contains(|c| !is_barestr(c)) {
- args.push(Arg::BareString(v.to_string()));
- } else {
- return Err("Invalid argument")
- }
-
- buf = splt.next().unwrap_or("");
- }
- },
- }
- buf = trim_ws(buf);
+ while buf.len() > 0 {
+ let v = parse_arg(buf)?;
+ msg = msg.push_arg(v.0);
+ buf = trim_ws(v.1);
}
- Ok(Message::new(name.to_string(), args))
+ Ok(msg)
}