This commit is contained in:
Alex 2022-11-18 18:59:06 +01:00
parent 24c7a9bbb5
commit 7a79994b00
Signed by: lx
GPG key ID: 0E496D15096376BE
7 changed files with 73 additions and 211 deletions

View file

@ -5,7 +5,9 @@ mod error;
use std::collections::HashMap;
#[cfg(any(feature = "blake2", feature = "ed25519-dalek"))]
use crate::crypto;
pub use decode::*;
pub use error::*;
@ -578,16 +580,6 @@ impl<'a, 'b> std::fmt::Debug for AnyTerm<'a, 'b> {
impl<'a, 'b> std::fmt::Debug for NonListTerm<'a, 'b> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self.mkref() {
NonListTerm::Str(s) => write!(f, "Str(`{}`)", debug(s)),
NonListTerm::DictRef(raw, d) => {
write!(f, "Dict<`{}`", debug(raw))?;
for (k, v) in d.iter() {
write!(f, "\n `{}`={:?}", debug(k), v)?;
}
write!(f, ">")
}
_ => unreachable!(),
}
AnyTerm::from(self.mkref()).fmt(f)
}
}

View file

@ -6,6 +6,7 @@ pub enum Error {
InvalidCharacter(u8),
InvalidRaw,
NotADictionnary,
DuplicateKey(String),
ListInList,
}
@ -15,6 +16,7 @@ impl std::fmt::Display for Error {
Error::InvalidCharacter(c) => write!(f, "Invalid character '{}'", *c as char),
Error::InvalidRaw => write!(f, "Invalid RAW nettext litteral"),
Error::NotADictionnary => write!(f, "Tried to insert into a term that isn't a dictionnary"),
Error::DuplicateKey(s) => write!(f, "Duplicate dict key: {}", s),
Error::ListInList => write!(f, "Refusing to build nested lists with list(), use either list_flatten() or list_nested()"),
}
}

View file

@ -13,7 +13,7 @@
//! ("b", string("world").unwrap()),
//! ("c", raw(b"{ a = 12, b = 42 }").unwrap()),
//! ("d", bytes_split(&((0..128u8).collect::<Vec<_>>()))),
//! ]),
//! ]).unwrap(),
//! ]).unwrap().encode();
//! ```
@ -94,13 +94,6 @@ pub fn raw(bytes: &[u8]) -> Result<'_> {
Ok(Term(T::Str(bytes)))
}
pub(crate) fn safe_raw(bytes: &[u8]) -> Term<'_> {
Term(T::Str(bytes))
}
pub(crate) fn safe_raw_owned(bytes: Vec<u8>) -> Term<'static> {
Term(T::OwnedStr(bytes))
}
/// Term corresponding to a list of terms
///
/// ```
@ -154,22 +147,16 @@ pub fn list_nested<'a, I: IntoIterator<Item = Term<'a>>>(terms: I) -> Result<'a>
/// assert_eq!(dict([
/// ("a", string("Hello").unwrap()),
/// ("b", string("world").unwrap())
/// ]).encode(), b"{\n a = Hello,\n b = world,\n}");
/// ]).unwrap().encode(), b"{\n a = Hello,\n b = world,\n}");
/// ```
pub fn dict<'a, I: IntoIterator<Item = (&'a str, Term<'a>)>>(pairs: I) -> Term<'a> {
pub fn dict<'a, I: IntoIterator<Item = (&'a str, Term<'a>)>>(pairs: I) -> Result<'a> {
let mut tmp = HashMap::new();
for (k, v) in pairs {
tmp.insert(Cow::from(k.as_bytes()), v.0);
if tmp.insert(Cow::from(k.as_bytes()), v.0).is_some() {
return Err(Error::DuplicateKey(k.to_string()));
}
}
Term(T::Dict(tmp))
}
pub(crate) fn dict_owned_u8<'a, I: IntoIterator<Item = (Vec<u8>, Term<'a>)>>(pairs: I) -> Term<'a> {
let mut tmp = HashMap::new();
for (k, v) in pairs {
tmp.insert(Cow::from(k), v.0);
}
Term(T::Dict(tmp))
Ok(Term(T::Dict(tmp)))
}
/// Term corresponding to a byte slice,
@ -223,7 +210,9 @@ impl<'a> Term<'a> {
pub fn insert(self, k: &'a str, v: Term<'a>) -> Result<'a> {
match self.0 {
T::Dict(mut d) => {
d.insert(Cow::from(k.as_bytes()), v.0);
if d.insert(Cow::from(k.as_bytes()), v.0).is_some() {
return Err(Error::DuplicateKey(k.to_string()));
}
Ok(Term(T::Dict(d)))
}
_ => Err(Error::NotADictionnary),
@ -242,10 +231,33 @@ impl<'a> Term<'a> {
/// ```
#[must_use]
pub fn nested(self) -> Term<'a> {
dict([(".", self)])
dict([(".", self)]).unwrap()
}
}
// ---- additional internal functions for serde module ----
#[cfg(feature = "serde")]
pub(crate) fn dict_owned_u8<'a, I: IntoIterator<Item = (Vec<u8>, Term<'a>)>>(
pairs: I,
) -> Result<'a> {
let mut tmp = HashMap::new();
for (k, v) in pairs {
tmp.insert(Cow::from(k), v.0);
}
Ok(Term(T::Dict(tmp)))
}
#[cfg(feature = "serde")]
pub(crate) fn safe_raw(bytes: &[u8]) -> Term<'_> {
Term(T::Str(bytes))
}
#[cfg(feature = "serde")]
pub(crate) fn safe_raw_owned(bytes: Vec<u8>) -> Term<'static> {
Term(T::OwnedStr(bytes))
}
// ---- encoding function ----
impl<'a> Term<'a> {
@ -267,13 +279,13 @@ impl<'a> T<'a> {
buf.extend_from_slice(b"{}");
} else if d.len() == 1 {
let (k, v) = d.into_iter().next().unwrap();
if k.as_ref() == b"." {
buf.extend_from_slice(b"{.= ");
} else {
buf.extend_from_slice(b"{ ");
buf.extend_from_slice(k.borrow());
buf.extend_from_slice(b" = ");
}
if k.as_ref() == b"." {
buf.extend_from_slice(b"{.= ");
} else {
buf.extend_from_slice(b"{ ");
buf.extend_from_slice(k.borrow());
buf.extend_from_slice(b" = ");
}
v.encode_aux(buf, indent + 2, false);
buf.extend_from_slice(b" }");
} else {
@ -328,7 +340,8 @@ mod tests {
("from", string("jxx").unwrap()),
("subject", string("hello").unwrap()),
("data", raw(b"{ f1 = plop, f2 = kuko }").unwrap()),
]),
])
.unwrap(),
])
.unwrap();
let expected = b"HELLO alexhelloworld {

View file

@ -16,7 +16,7 @@
//! ("b", string("world").unwrap()),
//! ("c", raw(b"{ a = 12, b = 42 }").unwrap()),
//! ("d", bytes_split(&((0..128u8).collect::<Vec<_>>()))),
//! ]),
//! ]).unwrap(),
//! keypair.public.term().unwrap(),
//! ]).unwrap().encode();
//! eprintln!("{}", std::str::from_utf8(&text1).unwrap());
@ -29,7 +29,7 @@
//! ("hash", hash.term().unwrap()),
//! ("signature", sign.term().unwrap()),
//! ("payload", raw(&text1).unwrap()),
//! ]).encode();
//! ]).unwrap().encode();
//! eprintln!("{}", std::str::from_utf8(&text2).unwrap());
//!
//! // Decode and check everything is fine

View file

@ -40,7 +40,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> {
where
V: Visitor<'de>,
{
Err(Error::custom("derialize_any not supported"))
Err(Error::custom(format!(
"deserialize_any not supported, at: `{}`",
self.0
)))
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
@ -400,9 +403,9 @@ impl<'de, 'a> EnumAccess<'de> for Enum<'de, 'a> {
where
V: DeserializeSeed<'de>,
{
let term = &self.0.list()[0];
let value = seed.deserialize(&mut Deserializer(Term(term.0.mkref())))?;
Ok((value, self))
let variant = &self.0.list()[0];
let variant = seed.deserialize(&mut Deserializer(Term(variant.0.mkref())))?;
Ok((variant, self))
}
}
@ -441,57 +444,3 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'de, 'a> {
visitor.visit_map(&mut Dict::from_term(&rest)?)
}
}
// ----
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_struct() {
#[derive(Deserialize, PartialEq, Debug)]
struct Test {
int: u32,
seq: Vec<String>,
}
let nt = br#"Test { int = 1, seq = YQ Yg }"#;
let expected = Test {
int: 1,
seq: vec!["a".to_owned(), "b".to_owned()],
};
assert_eq!(expected, from_bytes(nt).unwrap());
}
#[test]
fn test_enum() {
#[derive(Deserialize, PartialEq, Debug)]
enum E {
Unit,
Newtype(u32),
Tuple(u32, u32),
Struct { a: u32 },
}
let nt = br#"E.Unit"#;
let expected = E::Unit;
assert_eq!(expected, from_bytes(nt).unwrap());
eprintln!("UNIT OK");
let nt = br#"E.Newtype 1"#;
let expected = E::Newtype(1);
assert_eq!(expected, from_bytes(nt).unwrap());
eprintln!("NEWTYPE OK");
let nt = br#"E.Tuple 1 2"#;
let expected = E::Tuple(1, 2);
assert_eq!(expected, from_bytes(nt).unwrap());
eprintln!("TUPLE OK");
let nt = br#"E.Struct { a = 1 }"#;
let expected = E::Struct { a: 1 };
assert_eq!(expected, from_bytes(nt).unwrap());
eprintln!("STRUCT OK");
}
}

View file

@ -41,15 +41,15 @@ mod tests {
test_bidir(input, expected);
let input = vec![
Test {
int: 1,
seq: vec!["a".to_string(), "b".to_string()],
},
Test {
int: 2,
seq: vec!["c".to_string(), "d".to_string()],
},
];
Test {
int: 1,
seq: vec!["a".to_string(), "b".to_string()],
},
Test {
int: 2,
seq: vec!["c".to_string(), "d".to_string()],
},
];
let expected = br#"{.= Test {
int = 1,
seq = YQ Yg,
@ -94,7 +94,8 @@ mod tests {
E::Struct { a: 1 },
E::Tuple(3, 2),
];
let expected = br#"E.Unit E.Unit {.= E.Newtype 1 } {.= E.Tuple 1 2 } {.= E.Struct { a = 1 } } {.=
let expected =
br#"E.Unit E.Unit {.= E.Newtype 1 } {.= E.Tuple 1 2 } {.= E.Struct { a = 1 } } {.=
E.Tuple 3 2 }"#;
test_bidir(input, expected);
}

View file

@ -94,7 +94,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
}
fn serialize_none(self) -> Result<Self::Ok> {
Ok(dict([]))
Ok(dict([])?)
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
@ -105,7 +105,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
}
fn serialize_unit(self) -> Result<Self::Ok> {
Ok(dict([]))
Ok(dict([])?)
}
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
@ -309,7 +309,7 @@ impl ser::SerializeMap for MapSerializer {
}
fn end(self) -> Result<Term<'static>> {
Ok(dict_owned_u8(self.fields.into_iter()))
Ok(dict_owned_u8(self.fields.into_iter())?)
}
}
@ -331,7 +331,7 @@ impl ser::SerializeStruct for StructSerializer {
}
fn end(self) -> Result<Term<'static>> {
Ok(list([string(self.name)?, dict(self.fields.into_iter())])?)
Ok(list([string(self.name)?, dict(self.fields.into_iter())?])?)
}
}
@ -356,102 +356,7 @@ impl ser::SerializeStructVariant for StructVariantSerializer {
fn end(self) -> Result<Term<'static>> {
Ok(list([
string_owned(format!("{}.{}", self.name, self.variant))?,
dict(self.fields.into_iter()),
dict(self.fields.into_iter())?,
])?)
}
}
// ----
#[cfg(test)]
mod tests {
use super::*;
use serde::Serialize;
use std::collections::HashMap;
#[test]
fn test_struct() {
#[derive(Serialize)]
struct Test {
int: u32,
seq: Vec<&'static str>,
}
let test = Test {
int: 1,
seq: vec!["a", "b"],
};
let expected = br#"Test {
int = 1,
seq = YQ Yg,
}"#;
assert_eq!(&to_bytes(&test).unwrap(), expected);
}
#[test]
fn test_enum() {
#[derive(Serialize)]
enum E {
Unit,
Newtype(u32),
Tuple(u32, u32),
Struct { a: u32 },
}
let u = E::Unit;
let expected = br#"E.Unit"#;
assert_eq!(&to_bytes(&u).unwrap(), expected);
let n = E::Newtype(1);
let expected = br#"E.Newtype 1"#;
assert_eq!(&to_bytes(&n).unwrap(), expected);
let t = E::Tuple(1, 2);
let expected = br#"E.Tuple 1 2"#;
assert_eq!(&to_bytes(&t).unwrap(), expected);
let s = E::Struct { a: 1 };
let expected = br#"E.Struct { a = 1 }"#;
assert_eq!(&to_bytes(&s).unwrap(), expected);
}
#[test]
fn test_seq() {
let u = (1, 2, 3, 4);
let expected = br#"1 2 3 4"#;
assert_eq!(&to_bytes(&u).unwrap(), expected);
let n = (1, 2, (2, 3, 4), 5, 6);
let expected = br#"1 2 {.= 2 3 4 } 5 6"#;
assert_eq!(&to_bytes(&n).unwrap(), expected);
let t = [1, 2, 3, 4];
let expected = br#"1 2 3 4"#;
assert_eq!(&to_bytes(&t).unwrap(), expected);
let s = [[1, 2], [2, 3], [3, 4]];
let expected = br#"{.= 1 2 } {.= 2 3 } {.= 3 4 }"#;
assert_eq!(&to_bytes(&s).unwrap(), expected);
}
#[test]
fn test_dict() {
let mut d = HashMap::new();
d.insert("hello", "world");
d.insert("dont", "panic");
let expected = br#"{
ZG9udA = cGFuaWM,
aGVsbG8 = d29ybGQ,
}"#;
assert_eq!(&to_bytes(&d).unwrap(), expected);
let mut d = HashMap::new();
d.insert(12, vec![42, 125]);
d.insert(33, vec![19, 22, 21]);
let expected = br#"{
12 = 42 125,
33 = 19 22 21,
}"#;
assert_eq!(&to_bytes(&d).unwrap(), expected);
}
}