diff --git a/Cargo.toml b/Cargo.toml index 054ae09..31db578 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cirru_edn" -version = "0.2.0" +version = "0.2.1" authors = ["jiyinyiyong "] edition = "2018" license = "MIT" @@ -14,3 +14,4 @@ readme = "README.md" [dependencies] cirru_parser = "0.1.8" +hex = "0.3.0" \ No newline at end of file diff --git a/README.md b/README.md index a837399..e9bb405 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,12 @@ a record, notice that now it's all using keywords: :c $ [] 1 2 3 ``` +extra format for holding buffer, which is internally `Vec`: + +```cirru +buf 00 01 f1 11 +``` + ### License MIT diff --git a/examples/buffer.rs b/examples/buffer.rs new file mode 100644 index 0000000..93890b8 --- /dev/null +++ b/examples/buffer.rs @@ -0,0 +1,7 @@ +use cirru_edn::{parse, Edn}; + +pub fn main() { + println!("{}", Edn::Buffer(vec![1, 2, 3])); + + println!("{:?}", parse("buf 03 55 77 ff 00")); +} diff --git a/src/lib.rs b/src/lib.rs index 68deb44..26f8991 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -153,6 +153,33 @@ fn extract_cirru_edn(node: &Cirru) -> Result { Err(String::from("insufficient items for edn record")) } } + "buf" => { + let mut ys: Vec = vec![]; + for (idx, x) in xs.iter().enumerate() { + if idx > 0 { + match x { + Cirru::Leaf(y) => { + if y.len() == 2 { + match hex::decode(y) { + Ok(b) => { + if b.len() == 1 { + ys.push(b[0]) + } else { + return Err(format!("hex for buffer might be too large, got: {:?}", b)); + } + } + Err(e) => return Err(format!("expected length 2 hex string in buffer, got: {} {}", y, e)), + } + } else { + return Err(format!("expected length 2 hex string in buffer, got: {}", y)); + } + } + _ => return Err(format!("expected hex string in buffer, got: {}", x)), + } + } + } + Ok(Edn::Buffer(ys)) + } a => Err(format!("invalid operator for edn: {}", a)), }, Cirru::List(a) => Err(format!("invalid nodes for edn: {:?}", a)), @@ -230,6 +257,15 @@ fn assemble_cirru_node(data: &Edn) -> Cirru { ys.push(assemble_cirru_node(&*v.to_owned())); Cirru::List(ys) } + Edn::Buffer(buf) => { + let mut ys: Vec = vec![Cirru::Leaf(String::from("buf"))]; + for b in buf { + ys.push(Cirru::Leaf( + format!("{:#04x}", b).strip_prefix("0x").unwrap().to_owned(), + )); + } + Cirru::List(ys) + } } } diff --git a/src/primes.rs b/src/primes.rs index e0d6f44..0544476 100644 --- a/src/primes.rs +++ b/src/primes.rs @@ -23,6 +23,7 @@ pub enum Edn { Set(HashSet), Map(HashMap), Record(String, Vec<(String, Edn)>), + Buffer(Vec), } impl fmt::Display for Edn { @@ -72,6 +73,14 @@ impl fmt::Display for Edn { f.write_str(")") } + Self::Buffer(buf) => { + f.write_str("(buf")?; + for b in buf { + f.write_str(" ")?; + f.write_str(format!("{:#04x}", b).strip_prefix("0x").unwrap())?; + } + f.write_str(")") + } } } } @@ -144,6 +153,12 @@ impl Hash for Edn { name.hash(_state); entries.hash(_state); } + Self::Buffer(buf) => { + "buffer:".hash(_state); + for b in buf { + b.hash(_state); + } + } } } } @@ -199,6 +214,10 @@ impl Ord for Edn { (Self::List(_), _) => Less, (_, Self::List(_)) => Greater, + (Self::Buffer(a), Self::Buffer(b)) => a.cmp(b), + (Self::Buffer(_), _) => Less, + (_, Self::Buffer(_)) => Greater, + (Self::Set(a), Self::Set(b)) => match a.len().cmp(&b.len()) { Equal => unreachable!("TODO sets are not cmp ed"), // TODO a => a, @@ -243,6 +262,7 @@ impl PartialEq for Edn { (Self::Quote(a), Self::Quote(b)) => a == b, (Self::Tuple(tag1, v1), Self::Tuple(tag2, v2)) => tag1 == tag2 && v1 == v2, (Self::List(a), Self::List(b)) => a == b, + (Self::Buffer(a), Self::Buffer(b)) => a == b, (Self::Set(a), Self::Set(b)) => a == b, (Self::Map(a), Self::Map(b)) => a == b, (Self::Record(name1, entries1), Self::Record(name2, entries2)) => name1 == name2 && entries1 == entries2, diff --git a/tests/edn_tests.rs b/tests/edn_tests.rs index cd627c2..8c2472c 100644 --- a/tests/edn_tests.rs +++ b/tests/edn_tests.rs @@ -240,3 +240,30 @@ fn test_reader() -> Result<(), String> { assert_eq!(Edn::Map(dict).map_get("k2")?, Edn::Nil); Ok(()) } + +#[test] +fn test_buffer() -> Result<(), String> { + assert_eq!(Edn::Buffer(vec![]), cirru_edn::parse("buf").unwrap()); + assert_eq!(Edn::Buffer(vec![1]), cirru_edn::parse("buf 01").unwrap()); + assert_eq!(Edn::Buffer(vec![255]), cirru_edn::parse("buf ff").unwrap()); + assert_eq!(Edn::Buffer(vec![10]), cirru_edn::parse("buf 0a").unwrap()); + + assert_eq!( + cirru_edn::format(&Edn::Buffer(vec![]), true).unwrap().trim(), + String::from("buf") + ); + assert_eq!( + cirru_edn::format(&Edn::Buffer(vec![1]), true).unwrap().trim(), + String::from("buf 01") + ); + assert_eq!( + cirru_edn::format(&Edn::Buffer(vec![255]), true).unwrap().trim(), + String::from("buf ff") + ); + assert_eq!( + cirru_edn::format(&Edn::Buffer(vec![10]), true).unwrap().trim(), + String::from("buf 0a") + ); + + Ok(()) +}