From ba416c3aa04407df7dc1c2b06ef4a02b1d18654a Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Mon, 22 Jun 2020 13:39:15 +0200 Subject: pkgs/profpatsch/netencode: add support for bool Instead of adding a new type, it just uses the 2^1 natural, which has exactly two possibilities. --- pkgs/profpatsch/netencode/default.nix | 4 ++-- pkgs/profpatsch/netencode/netencode.rs | 36 ++++++++++++++++++++++++++++------ pkgs/profpatsch/netencode/spec.md | 12 +++++++++++- 3 files changed, 43 insertions(+), 9 deletions(-) (limited to 'pkgs/profpatsch/netencode') diff --git a/pkgs/profpatsch/netencode/default.nix b/pkgs/profpatsch/netencode/default.nix index 31c6fb8d..2297db51 100644 --- a/pkgs/profpatsch/netencode/default.nix +++ b/pkgs/profpatsch/netencode/default.nix @@ -23,12 +23,12 @@ let features = [ "std" "alloc" ]; }; - netencode-rs-common = tests: writeRustSimpleLib "encode" { + netencode-rs-common = tests: writeRustSimpleLib "netencode" { dependencies = [ nom ]; buildTests = tests; release = false; verbose = true; - } ./netencode.rs ; + } ./netencode.rs; netencode-rs-tests = netencode-rs-common true; diff --git a/pkgs/profpatsch/netencode/netencode.rs b/pkgs/profpatsch/netencode/netencode.rs index 481cbb49..a3744946 100644 --- a/pkgs/profpatsch/netencode/netencode.rs +++ b/pkgs/profpatsch/netencode/netencode.rs @@ -7,6 +7,8 @@ use std::io::Write; pub enum T { // Unit Unit, + // Boolean + N1(bool), // Naturals N3(u8), N6(u64), @@ -29,6 +31,8 @@ pub enum T { #[derive(Debug, PartialEq, Eq, Clone)] pub enum U<'a> { Unit, + // Boolean + N1(bool), // Naturals N3(u8), N6(u64), @@ -71,6 +75,7 @@ fn encode_tag(w: &mut W, tag: String, val: T) -> std::io::Result<()> { pub fn encode(w: &mut W, t: T) -> std::io::Result<()> { match t { T::Unit => write!(w, "u,"), + T::N1(b) => if b { write!(w, "n1:1,") } else { write!(w, "n1:0,") }, T::N3(n) => write!(w, "n3:{},", n), T::N6(n) => write!(w, "n6:{},", n), T::N7(n) => write!(w, "n7:{},", n), @@ -113,7 +118,7 @@ pub fn text(s: String) -> T { T::Text(s) } -mod parse { +pub mod parse { use super::{T, Tag, U}; use std::str::FromStr; @@ -173,6 +178,13 @@ mod parse { } } + fn bool_t<'a>() -> impl Fn(&'a [u8]) -> IResult<&'a [u8], bool> { + context("bool", alt(( + map(tag("n1:0,"), |_| false), + map(tag("n1:1,"), |_| true), + ))) + } + fn int_t<'a, I: FromStr + Neg>(t: &'static str) -> impl Fn(&'a [u8]) -> IResult<&[u8], I> { context( t, @@ -293,7 +305,7 @@ mod parse { ) } - fn u_u(s: &[u8]) -> IResult<&[u8], U> { + pub fn u_u(s: &[u8]) -> IResult<&[u8], U> { alt(( map(text_g(), U::Text), map(unit_t, |()| U::Unit), @@ -301,6 +313,7 @@ mod parse { map(list_g(), U::List), map(record_g(u_u), U::Record), + map(bool_t(), |u| U::N1(u)), map(uint_t("n3"), |u| U::N3(u)), map(uint_t("n6"), |u| U::N6(u)), map(uint_t("n7"), |u| U::N7(u)), @@ -309,7 +322,6 @@ mod parse { map(int_t("i7"), |u| U::I7(u)), // less common - map(uint_t("n1"), |u| U::N3(u)), map(uint_t("n2"), |u| U::N3(u)), map(uint_t("n4"), |u| U::N6(u)), map(uint_t("n5"), |u| U::N6(u)), @@ -329,6 +341,7 @@ mod parse { map(list_t, |l| T::List(Box::new(l))), map(record_t, |p| T::Record(p)), + map(bool_t(), |u| T::N1(u)), // 8, 64 and 128 bit map(uint_t("n3"), |u| T::N3(u)), map(uint_t("n6"), |u| T::N6(u)), @@ -338,7 +351,6 @@ mod parse { map(int_t("i7"), |u| T::I7(u)), // less common - map(uint_t("n1"), |u| T::N3(u)), map(uint_t("n2"), |u| T::N3(u)), map(uint_t("n4"), |u| T::N6(u)), map(uint_t("n5"), |u| T::N6(u)), @@ -362,6 +374,18 @@ mod parse { ); } + #[test] + fn test_parse_bool_t() { + assert_eq!( + bool_t()("n1:0,".as_bytes()), + Ok(("".as_bytes(), false)) + ); + assert_eq!( + bool_t()("n1:1,".as_bytes()), + Ok(("".as_bytes(), true)) + ); + } + #[test] fn test_parse_usize_t() { assert_eq!( @@ -490,12 +514,12 @@ mod parse { // { a: Unit // , foo: List } assert_eq!( - t_t("{49:<1:a|u,<3:foo|[30:<1:A|u,<1:A|u,<1:B|[7:i3:127,]]}".as_bytes()), + t_t("{52:<1:a|u,<3:foo|[33:<1:A|u,<1:A|n1:1,<1:B|[7:i3:127,]]}".as_bytes()), Ok(("".as_bytes(), T::Record(vec![ ("a".to_owned(), Box::new(T::Unit)), ("foo".to_owned(), Box::new(T::List(Box::new(vec![ T::Sum(Tag { tag: "A".to_owned(), val: Box::new(T::Unit) }), - T::Sum(Tag { tag: "A".to_owned(), val: Box::new(T::Unit) }), + T::Sum(Tag { tag: "A".to_owned(), val: Box::new(T::N1(true)) }), T::Sum(Tag { tag: "B".to_owned(), val: Box::new(T::List(Box::new(vec![T::I3(127)]))) }), ])))) ].into_iter().collect::>>()))) diff --git a/pkgs/profpatsch/netencode/spec.md b/pkgs/profpatsch/netencode/spec.md index cd38588c..e680034f 100644 --- a/pkgs/profpatsch/netencode/spec.md +++ b/pkgs/profpatsch/netencode/spec.md @@ -31,8 +31,18 @@ An implementation can define the biggest numbers it supports, and has to throw a Floats are not supported, you can implement fixed-size decimals or ratios using integers. +### booleans + +A boolean is represented as `n1`. + +* `n1:0,`: false +* `n1:1,`: true + +TODO: should we add `f,` and `t,`? + ### text + Text (`t`) that *must* be encoded as UTF-8, starting with its length in bytes: * The string `hello world` (11 bytes): `t11:hello world,` @@ -40,7 +50,7 @@ Text (`t`) that *must* be encoded as UTF-8, starting with its length in bytes: * The string `:,` (2 bytes): `t2::,,` * The empty sting `` (0 bytes): `t0:,` -Binary data is not supported, it hinders human readability. Try to use structured data, or use a different format. +TODO: add `b` for binary content. Even filesystem paths are not utf-8 encodable sometimes, yet the distinction of text with an encoding is useful, so we should keep `t` as is. ## tagged values -- cgit 1.4.1