From 08c221558f52ce5bfc9181aad7dac40028e97a59 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 15 Dec 2022 13:32:38 +0100 Subject: [PATCH] A list is now called a sequence; works the same --- Cargo.toml | 2 +- README.md | 26 ++++----- src/dec/decode.rs | 58 ++++++++++---------- src/dec/mod.rs | 134 +++++++++++++++++++++++----------------------- src/enc/error.rs | 4 +- src/enc/mod.rs | 60 ++++++++++----------- src/lib.rs | 4 +- src/serde/de.rs | 24 ++++----- src/serde/ser.rs | 16 +++--- 9 files changed, 163 insertions(+), 165 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b7e62e4..f9f7f5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "nettext" description = "A text-based data format for cryptographic network protocols" authors = ["Alex Auvolat "] -version = "0.2.3" +version = "0.3.0" edition = "2021" license = "AGPL-3.0" readme = "README.md" diff --git a/README.md b/README.md index c76ef64..6769a0a 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ A term can be of any of the following kinds: - a string, which may contain only ASCII alphanumeric terms and `.-_*?` - a dict, which maps strings (as defined above) to any term type -- a list, which is a consecutive sequence of at least 2 strings or dicts (can be mixed), simply separated by whitespace +- a sequence, consistuted of at least two of the above (can be mixed), simply separated by whitespace; sequences cannot be nested -Nested lists can be represented using a special dictionnary with a single key, `.`, +Nested sequences can be represented using a special dictionnary with a single key, `.`, for instance `TEST a { . = 0 4 2 1 9 7 0 } c`. Dicts are represented as follows: @@ -29,7 +29,7 @@ Dicts are represented as follows: } ``` -Lists are represented as follows: +Sequences are represented as follows: ``` term1 term2 term3 @@ -44,15 +44,15 @@ SENDTO alex { } ``` -The raw representation of a parsed dict or list is retained for hashing purposes. +The raw representation of a parsed dict or sequence is retained for hashing purposes. It in the sequence of bytes, in the encoded string, trimmed from whitespace at extremities, -that represents the encoded dict or list in that string. +that represents the encoded dict or sequence in that string. -In the complex stance example above, here are the lists and dicts and their raw representation: +In the complex stance example above, here are the sequence and dicts and their raw representation: -- the toplevel term is a list, whose raw representation is the entire encoded string (assuming no whitespace at beginning or end) -- the third term of the list is a dict, whose raw representation starts at `{` and ends at `}` -- the second mapping of the dict is a list, whose raw representation is exactly `blah blah`. +- the toplevel term is a sequence, whose raw representation is the entire encoded string (assuming no whitespace at beginning or end) +- the third term of the sequence is a dict, whose raw representation starts at `{` and ends at `}` +- the second mapping of the dict is a sequence, whose raw representation is exactly `blah blah`. Since strings cannot contain whitespace, they are always equivalent to their raw representation. @@ -61,12 +61,12 @@ Since strings cannot contain whitespace, they are always equivalent to their raw Terms can be interpreted in a number of different ways, depending on the context: - RAW: the term is interpreted as its raw encoding (see above) -- STRING: if the term is a string or a list composed exclusively of strings, the term is interpreted as its raw encoding -- VARIANT: if the term is a list whose first item is a string, it is interpreted as a variant with the following properties: +- STRING: if the term is a string or a sequence composed exclusively of strings, the term is interpreted as its raw encoding +- VARIANT: if the term is a sequence whose first item is a string, it is interpreted as a variant with the following properties: - a discriminator (the first item) - - a value, which is either the second item in case there are only two items, or the list composed of all items starting from the second if there are more than two + - a value, which is either the second item in case there are only two items, or the sequence composed of all items starting from the second if there are more than two - DICT: if the term is a dict, interpret it as such -- LIST: if the term is a string or a dict, interpret it as a list composed of that single term. Otherwise, the term is a list, interpret it as a list of terms. +- SEQ: if the term is a string or a dict, interpret it as a sequence composed of that single term. Otherwise, the term is a sequence, interpret it as a sequence of terms. - NESTED: if the term is a dict with a single key `.`, interpret it as the term associated to that key ## Data mappings diff --git a/src/dec/decode.rs b/src/dec/decode.rs index 73f6b26..7eafb73 100644 --- a/src/dec/decode.rs +++ b/src/dec/decode.rs @@ -8,7 +8,7 @@ use nom::{ IResult, InputLength, }; -use crate::dec::{AnyTerm, DecodeError, NonListTerm, Term}; +use crate::dec::{AnyTerm, DecodeError, NonSeqTerm, Term}; use crate::{is_string_char, is_whitespace, DICT_ASSIGN, DICT_CLOSE, DICT_DELIM, DICT_OPEN}; // ---- @@ -25,21 +25,21 @@ pub fn decode(input: &[u8]) -> std::result::Result, DecodeError<'_> fn decode_term(input: &[u8]) -> IResult<&'_ [u8], AnyTerm<'_, '_>> { let (start, _) = take_while(is_whitespace)(input)?; - let (rest, list) = separated_list1(take_while1(is_whitespace), decode_nonlist_term)(start)?; + let (rest, seq) = separated_list1(take_while1(is_whitespace), decode_nonseq_term)(start)?; - if list.len() == 1 { - Ok((rest, list.into_iter().next().unwrap().into())) + if seq.len() == 1 { + Ok((rest, seq.into_iter().next().unwrap().into())) } else { let raw_len = start.input_len() - rest.input_len(); - let list_raw = &start[..raw_len]; - Ok((rest, AnyTerm::List(list_raw, list))) + let seq_raw = &start[..raw_len]; + Ok((rest, AnyTerm::Seq(seq_raw, seq))) } } -fn decode_nonlist_term(input: &[u8]) -> IResult<&'_ [u8], NonListTerm<'_, '_>> { +fn decode_nonseq_term(input: &[u8]) -> IResult<&'_ [u8], NonSeqTerm<'_, '_>> { let (rest, term) = alt(( - map(decode_str, NonListTerm::Str), - map(decode_dict, |(raw, d)| NonListTerm::Dict(raw, d)), + map(decode_str, NonSeqTerm::Str), + map(decode_dict, |(raw, d)| NonSeqTerm::Dict(raw, d)), ))(input)?; Ok((rest, term)) } @@ -94,17 +94,17 @@ mod tests { } #[test] - fn list_of_str_str() { + fn seq_of_str_str() { let bytes = b" plop plap plip ploup "; assert_eq!( decode(bytes), - Ok(AnyTerm::List( + Ok(AnyTerm::Seq( b"plop plap plip ploup", vec![ - NonListTerm::Str(b"plop"), - NonListTerm::Str(b"plap"), - NonListTerm::Str(b"plip"), - NonListTerm::Str(b"ploup"), + NonSeqTerm::Str(b"plop"), + NonSeqTerm::Str(b"plap"), + NonSeqTerm::Str(b"plip"), + NonSeqTerm::Str(b"ploup"), ] ) .into()) @@ -122,9 +122,9 @@ mod tests { (&b"aze"[..], AnyTerm::Str(b"hello")), ( &b"by"[..], - AnyTerm::List( + AnyTerm::Seq( b"bojzkz pipo", - vec![NonListTerm::Str(b"bojzkz"), NonListTerm::Str(b"pipo")] + vec![NonSeqTerm::Str(b"bojzkz"), NonSeqTerm::Str(b"pipo")] ) ), (&b"ccde"[..], AnyTerm::Str(b"ke")), @@ -147,9 +147,9 @@ mod tests { (&b"aze"[..], AnyTerm::Str(b"hello")), ( &b"by"[..], - AnyTerm::List( + AnyTerm::Seq( b"bojzkz pipo", - vec![NonListTerm::Str(b"bojzkz"), NonListTerm::Str(b"pipo")] + vec![NonSeqTerm::Str(b"bojzkz"), NonSeqTerm::Str(b"pipo")] ) ), (&b"ccde"[..], AnyTerm::Str(b"ke")), @@ -166,9 +166,9 @@ mod tests { let bytes = b"HEAD alexpubkey"; assert_eq!( decode(bytes), - Ok(AnyTerm::List( + Ok(AnyTerm::Seq( b"HEAD alexpubkey", - vec![NonListTerm::Str(b"HEAD"), NonListTerm::Str(b"alexpubkey")] + vec![NonSeqTerm::Str(b"HEAD"), NonSeqTerm::Str(b"alexpubkey")] ) .into()), ); @@ -179,22 +179,22 @@ mod tests { let bytes = b"STANCE sthash stsign { author = alexpubkey, height = 12, parent = parenthash, data = MESSAGE { text = hello } }"; assert_eq!( decode(bytes), - Ok(AnyTerm::List( + Ok(AnyTerm::Seq( &bytes[..], vec![ - NonListTerm::Str(b"STANCE"), - NonListTerm::Str(b"sthash"), - NonListTerm::Str(b"stsign"), - NonListTerm::Dict(b"{ author = alexpubkey, height = 12, parent = parenthash, data = MESSAGE { text = hello } }", + NonSeqTerm::Str(b"STANCE"), + NonSeqTerm::Str(b"sthash"), + NonSeqTerm::Str(b"stsign"), + NonSeqTerm::Dict(b"{ author = alexpubkey, height = 12, parent = parenthash, data = MESSAGE { text = hello } }", [ (&b"author"[..], AnyTerm::Str(b"alexpubkey")), (&b"height"[..], AnyTerm::Str(b"12")), (&b"parent"[..], AnyTerm::Str(b"parenthash")), - (&b"data"[..], AnyTerm::List( + (&b"data"[..], AnyTerm::Seq( b"MESSAGE { text = hello }", vec![ - NonListTerm::Str(b"MESSAGE"), - NonListTerm::Dict( + NonSeqTerm::Str(b"MESSAGE"), + NonSeqTerm::Dict( b"{ text = hello }", [ (&b"text"[..], AnyTerm::Str(b"hello")), diff --git a/src/dec/mod.rs b/src/dec/mod.rs index 1953830..2bacf11 100644 --- a/src/dec/mod.rs +++ b/src/dec/mod.rs @@ -26,34 +26,34 @@ pub(crate) enum AnyTerm<'a, 'b> { Str(&'a [u8]), Dict(&'a [u8], HashMap<&'a [u8], AnyTerm<'a, 'b>>), DictRef(&'a [u8], &'b HashMap<&'a [u8], AnyTerm<'a, 'b>>), - List(&'a [u8], Vec>), - ListRef(&'a [u8], &'b [NonListTerm<'a, 'b>]), + Seq(&'a [u8], Vec>), + SeqRef(&'a [u8], &'b [NonSeqTerm<'a, 'b>]), } #[derive(Eq, PartialEq, Clone)] -pub(crate) enum NonListTerm<'a, 'b> { +pub(crate) enum NonSeqTerm<'a, 'b> { Str(&'a [u8]), Dict(&'a [u8], HashMap<&'a [u8], AnyTerm<'a, 'b>>), DictRef(&'a [u8], &'b HashMap<&'a [u8], AnyTerm<'a, 'b>>), } -impl<'a, 'b> From> for AnyTerm<'a, 'b> { - fn from(x: NonListTerm<'a, 'b>) -> AnyTerm<'a, 'b> { +impl<'a, 'b> From> for AnyTerm<'a, 'b> { + fn from(x: NonSeqTerm<'a, 'b>) -> AnyTerm<'a, 'b> { match x { - NonListTerm::Str(s) => AnyTerm::Str(s), - NonListTerm::Dict(raw, d) => AnyTerm::Dict(raw, d), - NonListTerm::DictRef(raw, d) => AnyTerm::DictRef(raw, d), + NonSeqTerm::Str(s) => AnyTerm::Str(s), + NonSeqTerm::Dict(raw, d) => AnyTerm::Dict(raw, d), + NonSeqTerm::DictRef(raw, d) => AnyTerm::DictRef(raw, d), } } } -impl<'a, 'b> TryFrom> for NonListTerm<'a, 'b> { +impl<'a, 'b> TryFrom> for NonSeqTerm<'a, 'b> { type Error = (); - fn try_from(x: AnyTerm<'a, 'b>) -> Result, ()> { + fn try_from(x: AnyTerm<'a, 'b>) -> Result, ()> { match x { - AnyTerm::Str(s) => Ok(NonListTerm::Str(s)), - AnyTerm::Dict(raw, d) => Ok(NonListTerm::Dict(raw, d)), - AnyTerm::DictRef(raw, d) => Ok(NonListTerm::DictRef(raw, d)), + AnyTerm::Str(s) => Ok(NonSeqTerm::Str(s)), + AnyTerm::Dict(raw, d) => Ok(NonSeqTerm::Dict(raw, d)), + AnyTerm::DictRef(raw, d) => Ok(NonSeqTerm::DictRef(raw, d)), _ => Err(()), } } @@ -118,7 +118,7 @@ impl<'a, 'b> Term<'a, 'b> { } } - /// If the term is a single string, or a list containing only strings, + /// If the term is a single string, or a sequence containing only strings, /// get its raw representation /// /// Example: @@ -135,16 +135,16 @@ impl<'a, 'b> Term<'a, 'b> { pub fn string(&self) -> Result<&'a str, TypeError> { match &self.0 { AnyTerm::Str(s) => Ok(std::str::from_utf8(s)?), - AnyTerm::List(r, l) if l.iter().all(|x| matches!(x, NonListTerm::Str(_))) => { + AnyTerm::Seq(r, l) if l.iter().all(|x| matches!(x, NonSeqTerm::Str(_))) => { Ok(std::str::from_utf8(r)?) } _ => Err(TypeError::WrongType("STRING")), } } - /// Return a list of terms made from this term. - /// If it is a str or a dict, returns a list of a single term. - /// If it is a list, that's the list of terms we return. + /// Return a sequence of terms made from this term. + /// If it is a str or a dict, returns a seq of a single term. + /// If it is a sequence, that's the seq of terms we return. /// /// Example: /// @@ -152,26 +152,26 @@ impl<'a, 'b> Term<'a, 'b> { /// use nettext::dec::decode; /// /// let term1 = decode(b"hello").unwrap(); - /// let list1 = term1.list(); - /// assert_eq!(list1.len(), 1); - /// assert_eq!(list1[0].str().unwrap(), "hello"); + /// let seq1 = term1.seq(); + /// assert_eq!(seq1.len(), 1); + /// assert_eq!(seq1[0].str().unwrap(), "hello"); /// /// let term2 = decode(b"hello world").unwrap(); - /// let list2 = term2.list(); - /// assert_eq!(list2.len(), 2); - /// assert_eq!(list2[0].str().unwrap(), "hello"); - /// assert_eq!(list2[1].str().unwrap(), "world"); + /// let seq2 = term2.seq(); + /// assert_eq!(seq2.len(), 2); + /// assert_eq!(seq2[0].str().unwrap(), "hello"); + /// assert_eq!(seq2[1].str().unwrap(), "world"); /// ``` - pub fn list(&self) -> Vec> { + pub fn seq(&self) -> Vec> { match self.0.mkref() { - AnyTerm::ListRef(_r, l) => l.iter().map(|x| Term(x.mkref().into())).collect::>(), + AnyTerm::SeqRef(_r, l) => l.iter().map(|x| Term(x.mkref().into())).collect::>(), x => vec![Term(x)], } } - /// Same as `.list()`, but deconstructs it in a const length array, + /// Same as `.seq()`, but deconstructs it in a const length array, /// dynamically checking if there are the correct number of items. - /// This allows to directly bind the resulting list into discrete variables. + /// This allows to directly bind the resulting seq into discrete variables. /// /// Example: /// @@ -179,24 +179,24 @@ impl<'a, 'b> Term<'a, 'b> { /// use nettext::dec::decode; /// /// let term1 = decode(b"hello").unwrap(); - /// let [s1] = term1.list_of().unwrap(); + /// let [s1] = term1.seq_of().unwrap(); /// assert_eq!(s1.str().unwrap(), "hello"); /// /// let term2 = decode(b"hello world").unwrap(); - /// let [s2a, s2b] = term2.list_of().unwrap(); + /// let [s2a, s2b] = term2.seq_of().unwrap(); /// assert_eq!(s2a.str().unwrap(), "hello"); /// assert_eq!(s2b.str().unwrap(), "world"); /// ``` - pub fn list_of(&self) -> Result<[Term<'a, '_>; N], TypeError> { - let list = self.list(); - let list_len = list.len(); - list.try_into() - .map_err(|_| TypeError::WrongLength(list_len, N)) + pub fn seq_of(&self) -> Result<[Term<'a, '_>; N], TypeError> { + let seq = self.seq(); + let seq_len = seq.len(); + seq.try_into() + .map_err(|_| TypeError::WrongLength(seq_len, N)) } - /// Same as `.list_of()`, but only binds the first N-1 terms. + /// Same as `.seq_of()`, but only binds the first N-1 terms. /// If there are exactly N terms, the last one is bound to the Nth return variable. - /// If there are more then N terms, the remaining terms are bound to a new list term + /// If there are more then N terms, the remaining terms are bound to a new seq term /// that is returned as the Nth return variable. /// /// Example: @@ -205,21 +205,21 @@ impl<'a, 'b> Term<'a, 'b> { /// use nettext::dec::decode; /// /// let term1 = decode(b"hello world").unwrap(); - /// let [s1a, s1b] = term1.list_of_first().unwrap(); + /// let [s1a, s1b] = term1.seq_of_first().unwrap(); /// assert_eq!(s1a.str().unwrap(), "hello"); /// assert_eq!(s1b.str().unwrap(), "world"); /// /// let term2 = decode(b"hello mighty world").unwrap(); - /// let [s2a, s2b] = term2.list_of_first().unwrap(); + /// let [s2a, s2b] = term2.seq_of_first().unwrap(); /// assert_eq!(s2a.str().unwrap(), "hello"); - /// assert_eq!(s2b.list().len(), 2); + /// assert_eq!(s2b.seq().len(), 2); /// assert_eq!(s2b.raw(), b"mighty world"); /// ``` - pub fn list_of_first(&self) -> Result<[Term<'a, '_>; N], TypeError> { + pub fn seq_of_first(&self) -> Result<[Term<'a, '_>; N], TypeError> { match self.0.mkref() { - AnyTerm::ListRef(raw, list) => match list.len().cmp(&N) { - std::cmp::Ordering::Less => Err(TypeError::WrongLength(list.len(), N)), - std::cmp::Ordering::Equal => Ok(list + AnyTerm::SeqRef(raw, seq) => match seq.len().cmp(&N) { + std::cmp::Ordering::Less => Err(TypeError::WrongLength(seq.len(), N)), + std::cmp::Ordering::Equal => Ok(seq .iter() .map(|x| Term(x.mkref().into())) .collect::>() @@ -227,15 +227,15 @@ impl<'a, 'b> Term<'a, 'b> { .unwrap()), std::cmp::Ordering::Greater => { let mut ret = Vec::with_capacity(N); - for item in list[0..N - 1].iter() { + for item in seq[0..N - 1].iter() { ret.push(Term(item.mkref().into())); } - let remaining_begin = list[N - 1].raw().as_ptr() as usize; + let remaining_begin = seq[N - 1].raw().as_ptr() as usize; let remaining_offset = remaining_begin - raw.as_ptr() as usize; let remaining_raw = &raw[remaining_offset..]; - ret.push(Term(AnyTerm::ListRef(remaining_raw, &list[N - 1..]))); + ret.push(Term(AnyTerm::SeqRef(remaining_raw, &seq[N - 1..]))); Ok(ret.try_into().unwrap()) } @@ -275,7 +275,7 @@ impl<'a, 'b> Term<'a, 'b> { } /// Checks term is a dictionnary whose keys are exactly those supplied, - /// and returns the associated values as a list. + /// and returns the associated values as a seq. /// /// Example: /// @@ -317,7 +317,7 @@ impl<'a, 'b> Term<'a, 'b> { } /// Checks term is a dictionnary whose keys are included in those supplied, - /// and returns the associated values as a list of options. + /// and returns the associated values as a seq of options. /// /// Example: /// @@ -419,10 +419,10 @@ impl<'a, 'b> Term<'a, 'b> { decode(encoded) } } - AnyTerm::ListRef(_, list) => { + AnyTerm::SeqRef(_, seq) => { let mut ret = Vec::with_capacity(128); - for term in list.iter() { - if let NonListTerm::Str(encoded) = term { + for term in seq.iter() { + if let NonSeqTerm::Str(encoded) = term { ret.extend(decode(encoded)?) } else { return Err(TypeError::WrongType("BYTES")); @@ -508,8 +508,8 @@ impl<'a, 'b> AnyTerm<'a, 'b> { AnyTerm::Str(s) => s, AnyTerm::Dict(r, _) | AnyTerm::DictRef(r, _) - | AnyTerm::List(r, _) - | AnyTerm::ListRef(r, _) => r, + | AnyTerm::Seq(r, _) + | AnyTerm::SeqRef(r, _) => r, } } @@ -518,25 +518,25 @@ impl<'a, 'b> AnyTerm<'a, 'b> { AnyTerm::Str(s) => AnyTerm::Str(s), AnyTerm::Dict(r, d) => AnyTerm::DictRef(r, d), AnyTerm::DictRef(r, d) => AnyTerm::DictRef(r, d), - AnyTerm::List(r, l) => AnyTerm::ListRef(r, &l[..]), - AnyTerm::ListRef(r, l) => AnyTerm::ListRef(r, l), + AnyTerm::Seq(r, l) => AnyTerm::SeqRef(r, &l[..]), + AnyTerm::SeqRef(r, l) => AnyTerm::SeqRef(r, l), } } } -impl<'a, 'b> NonListTerm<'a, 'b> { +impl<'a, 'b> NonSeqTerm<'a, 'b> { fn raw(&self) -> &'a [u8] { match &self { - NonListTerm::Str(s) => s, - NonListTerm::Dict(r, _) | NonListTerm::DictRef(r, _) => r, + NonSeqTerm::Str(s) => s, + NonSeqTerm::Dict(r, _) | NonSeqTerm::DictRef(r, _) => r, } } - fn mkref(&self) -> NonListTerm<'a, '_> { + fn mkref(&self) -> NonSeqTerm<'a, '_> { match &self { - NonListTerm::Str(s) => NonListTerm::Str(s), - NonListTerm::Dict(r, d) => NonListTerm::DictRef(r, d), - NonListTerm::DictRef(r, d) => NonListTerm::DictRef(r, d), + NonSeqTerm::Str(s) => NonSeqTerm::Str(s), + NonSeqTerm::Dict(r, d) => NonSeqTerm::DictRef(r, d), + NonSeqTerm::DictRef(r, d) => NonSeqTerm::DictRef(r, d), } } } @@ -576,8 +576,8 @@ impl<'a, 'b> std::fmt::Debug for AnyTerm<'a, 'b> { } write!(f, ">") } - AnyTerm::ListRef(raw, l) => { - write!(f, "List[`{}`", debug(raw))?; + AnyTerm::SeqRef(raw, l) => { + write!(f, "Seq[`{}`", debug(raw))?; for i in l.iter() { write!(f, "\n {:?}", i)?; } @@ -588,7 +588,7 @@ impl<'a, 'b> std::fmt::Debug for AnyTerm<'a, 'b> { } } -impl<'a, 'b> std::fmt::Debug for NonListTerm<'a, 'b> { +impl<'a, 'b> std::fmt::Debug for NonSeqTerm<'a, 'b> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { AnyTerm::from(self.mkref()).fmt(f) } diff --git a/src/enc/error.rs b/src/enc/error.rs index 666e85f..838f7de 100644 --- a/src/enc/error.rs +++ b/src/enc/error.rs @@ -12,7 +12,7 @@ pub enum Error { #[error(display = "Duplicate key: {}", _0)] DuplicateKey(String), #[error( - display = "Refusing to build nested lists with list(), use either list_flatten() or list_nested()" + display = "Refusing to build nested sequencess with seq(), use either seq_flatten() or seq_nested()" )] - ListInList, + SeqInSeq, } diff --git a/src/enc/mod.rs b/src/enc/mod.rs index c2b74c9..fb05ce6 100644 --- a/src/enc/mod.rs +++ b/src/enc/mod.rs @@ -5,7 +5,7 @@ //! ``` //! use nettext::enc::*; //! -//! let nettext_encoding = list([ +//! let nettext_encoding = seq([ //! string("CALL").unwrap(), //! string("myfunction").unwrap(), //! dict([ @@ -34,7 +34,7 @@ enum T<'a> { Str(&'a [u8]), OwnedStr(Vec), Dict(HashMap, T<'a>>), - List(Vec>), + Seq(Vec>), } /// The result type for trying to encode something as nettext @@ -95,49 +95,49 @@ pub fn raw(bytes: &[u8]) -> Result<'_> { Ok(Term(T::Str(bytes))) } -/// Term corresponding to a list of terms +/// Term corresponding to a sequence of terms /// /// ``` /// use nettext::enc::*; /// -/// assert_eq!(list([ +/// assert_eq!(seq([ /// string("Hello").unwrap(), /// string("world").unwrap() /// ]).unwrap().encode(), b"Hello world"); /// ``` -pub fn list<'a, I: IntoIterator>>(terms: I) -> Result<'a> { +pub fn seq<'a, I: IntoIterator>>(terms: I) -> Result<'a> { let mut tmp = Vec::with_capacity(8); for t in terms { match t.0 { - T::List(_) => return Err(Error::ListInList), + T::Seq(_) => return Err(Error::SeqInSeq), x => tmp.push(x), } } - Ok(Term(T::List(tmp))) + Ok(Term(T::Seq(tmp))) } -/// Term corresponding to a list of terms. Sub-lists are flattenned. -pub fn list_flatten<'a, I: IntoIterator>>(terms: I) -> Result<'a> { +/// Term corresponding to a sequence of terms. Sub-sequences are flattenned. +pub fn seq_flatten<'a, I: IntoIterator>>(terms: I) -> Result<'a> { let mut tmp = Vec::with_capacity(8); for t in terms { match t.0 { - T::List(t) => tmp.extend(t), + T::Seq(t) => tmp.extend(t), x => tmp.push(x), } } - Ok(Term(T::List(tmp))) + Ok(Term(T::Seq(tmp))) } -/// Term corresponding to a list of terms. Sub-lists are represented as NESTED: `{.= sub list items }`. -pub fn list_nested<'a, I: IntoIterator>>(terms: I) -> Result<'a> { +/// Term corresponding to a sequence of terms. Sub-sequences are represented as NESTED: `{.= sub sequence items }`. +pub fn seq_nested<'a, I: IntoIterator>>(terms: I) -> Result<'a> { let mut tmp = Vec::with_capacity(8); for t in terms { match t.0 { - T::List(t) => tmp.push(Term(T::List(t)).nested().0), + T::Seq(t) => tmp.push(Term(T::Seq(t)).nested().0), x => tmp.push(x), } } - Ok(Term(T::List(tmp))) + Ok(Term(T::Seq(tmp))) } /// Term corresponding to a dictionnary of items @@ -177,7 +177,7 @@ pub fn bytes(bytes: &[u8]) -> Term<'static> { } /// Same as `bytes()`, but splits the byte slice in 48-byte chunks -/// and encodes each chunk separately, putting them in a list of terms. +/// and encodes each chunk separately, putting them in a sequence of terms. /// Usefull for long byte slices to have cleaner representations, /// mainly usefull for dictionnary keys. pub fn bytes_split(bytes: &[u8]) -> Term<'static> { @@ -186,7 +186,7 @@ pub fn bytes_split(bytes: &[u8]) -> Term<'static> { .map(|b| T::OwnedStr(base64::encode_config(b, base64::URL_SAFE_NO_PAD).into_bytes())) .collect::>(); if chunks.len() > 1 { - Term(T::List(chunks)) + Term(T::Seq(chunks)) } else { Term(chunks.into_iter().next().unwrap_or(T::Str(b"."))) } @@ -194,15 +194,15 @@ pub fn bytes_split(bytes: &[u8]) -> Term<'static> { impl<'a> Term<'a> { /// Append a term to an existing term. - /// Transforms the initial term into a list if necessary. + /// Transforms the initial term into a seq if necessary. #[must_use] pub fn append(self, t: Term<'a>) -> Term<'a> { match self.0 { - T::List(mut v) => { + T::Seq(mut v) => { v.push(t.0); - Term(T::List(v)) + Term(T::Seq(v)) } - x => Term(T::List(vec![x, t.0])), + x => Term(T::Seq(vec![x, t.0])), } } @@ -228,7 +228,7 @@ impl<'a> Term<'a> { /// ``` /// use nettext::enc::*; /// - /// assert_eq!(list([string("hello").unwrap(), string("world").unwrap()]).unwrap().nested().encode(), b"{.= hello world }"); + /// assert_eq!(seq([string("hello").unwrap(), string("world").unwrap()]).unwrap().nested().encode(), b"{.= hello world }"); /// ``` #[must_use] pub fn nested(self) -> Term<'a> { @@ -271,9 +271,7 @@ impl<'a> Term<'a> { /// Generate the nettext representation of a term, as a String pub fn encode_string(self) -> String { - unsafe { - String::from_utf8_unchecked(self.encode()) - } + unsafe { String::from_utf8_unchecked(self.encode()) } } } @@ -317,7 +315,7 @@ impl<'a> T<'a> { buf.push(b'}'); } } - T::List(l) => { + T::Seq(l) => { let indent2 = indent + 2; for (i, v) in l.into_iter().enumerate() { if !is_toplevel && buf.iter().rev().take_while(|c| **c != b'\n').count() >= 70 { @@ -341,7 +339,7 @@ mod tests { #[test] fn complex1() { - let input = list([ + let input = seq([ string("HELLO").unwrap(), string("alexhelloworld").unwrap(), dict([ @@ -365,18 +363,18 @@ mod tests { #[test] fn nested() { - assert!(list([ + assert!(seq([ string("a").unwrap(), string("b").unwrap(), - list([string("c").unwrap(), string("d").unwrap()]).unwrap() + seq([string("c").unwrap(), string("d").unwrap()]).unwrap() ]) .is_err()); assert_eq!( - list([ + seq([ string("a").unwrap(), string("b").unwrap(), - list([string("c").unwrap(), string("d").unwrap()]) + seq([string("c").unwrap(), string("d").unwrap()]) .unwrap() .nested() ]) diff --git a/src/lib.rs b/src/lib.rs index 1a7c96a..5dc2417 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ //! let keypair = SigningKeyPair::gen_with_defaults(); //! //! // Encode a fist object that represents a payload that will be hashed and signed -//! let signed_payload = list([ +//! let signed_payload = seq([ //! string("CALL").unwrap(), //! string("myfunction").unwrap(), //! dict([ @@ -44,7 +44,7 @@ //! //! let object2 = decode(payload.raw()).unwrap(); //! -//! let [verb, arg1, arg2, pubkey] = object2.list_of().unwrap(); +//! let [verb, arg1, arg2, pubkey] = object2.seq_of().unwrap(); //! let pubkey = pubkey.public_key().unwrap(); //! assert!(verify_signature(&signature, payload.raw(), &pubkey)); //! diff --git a/src/serde/de.rs b/src/serde/de.rs index 9cd581a..83e0cbe 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -228,7 +228,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> { where V: Visitor<'de>, { - let [variant, args] = self.0.list_of_first()?; + let [variant, args] = self.0.seq_of_first()?; if variant.string()? == name { visitor.visit_newtype_struct(&mut Deserializer(args)) } else { @@ -244,14 +244,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> { where V: Visitor<'de>, { - visitor.visit_seq(&mut Seq(&self.0.list())) + visitor.visit_seq(&mut Seq(&self.0.seq())) } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { - visitor.visit_seq(&mut Seq(&self.0.list())) + visitor.visit_seq(&mut Seq(&self.0.seq())) } fn deserialize_tuple_struct( @@ -263,9 +263,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> { where V: Visitor<'de>, { - let [variant, args] = self.0.list_of_first()?; + let [variant, args] = self.0.seq_of_first()?; if variant.string()? == name { - visitor.visit_seq(&mut Seq(&args.list())) + visitor.visit_seq(&mut Seq(&args.seq())) } else { Err(Error::custom(format!( "Expected {}, got: `{}`", @@ -291,7 +291,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> { where V: Visitor<'de>, { - let [variant, data] = self.0.list_of()?; + let [variant, data] = self.0.seq_of()?; if variant.string()? != name { return Err(Error::custom(format!( "Expected {}, got: `{}`", @@ -414,7 +414,7 @@ impl<'de, 'a> EnumAccess<'de> for Enum<'de, 'a> { where V: DeserializeSeed<'de>, { - let variant = &self.0.list()[0]; + let variant = &self.0.seq()[0]; let variant = seed.deserialize(&mut Deserializer(Term(variant.0.mkref())))?; Ok((variant, self)) } @@ -424,7 +424,7 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'de, 'a> { type Error = Error; fn unit_variant(self) -> Result<()> { - if self.0.list().len() > 1 { + if self.0.seq().len() > 1 { Err(Error::custom("Spurrious data in unit variant")) } else { Ok(()) @@ -435,7 +435,7 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'de, 'a> { where T: DeserializeSeed<'de>, { - let [_, rest] = self.0.list_of_first()?; + let [_, rest] = self.0.seq_of_first()?; seed.deserialize(&mut Deserializer(rest)) } @@ -443,15 +443,15 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'de, 'a> { where V: Visitor<'de>, { - let [_, rest] = self.0.list_of_first()?; - visitor.visit_seq(&mut Seq(&rest.list())) + let [_, rest] = self.0.seq_of_first()?; + visitor.visit_seq(&mut Seq(&rest.seq())) } fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result where V: Visitor<'de>, { - let [_, rest] = self.0.list_of_first()?; + let [_, rest] = self.0.seq_of_first()?; visitor.visit_map(&mut Dict::from_term(&rest)?) } } diff --git a/src/serde/ser.rs b/src/serde/ser.rs index bf42203..8c83977 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -128,7 +128,7 @@ impl<'a> ser::Serializer for &'a mut Serializer { where T: ?Sized + Serialize, { - Ok(list_flatten([string(name)?, value.serialize(self)?])?) + Ok(seq_flatten([string(name)?, value.serialize(self)?])?) } fn serialize_newtype_variant( @@ -141,7 +141,7 @@ impl<'a> ser::Serializer for &'a mut Serializer { where T: ?Sized + Serialize, { - Ok(list_flatten([ + Ok(seq_flatten([ string_owned(format!("{}.{}", name, variant))?, value.serialize(self)?, ])?) @@ -226,7 +226,7 @@ impl ser::SerializeSeq for SeqSerializer { } fn end(self) -> Result { - Ok(list_nested(self.items.into_iter())?) + Ok(seq_nested(self.items.into_iter())?) } } @@ -243,7 +243,7 @@ impl ser::SerializeTuple for SeqSerializer { } fn end(self) -> Result { - Ok(list_nested(self.items.into_iter())?) + Ok(seq_nested(self.items.into_iter())?) } } @@ -260,7 +260,7 @@ impl ser::SerializeTupleStruct for SeqSerializer { } fn end(self) -> Result { - Ok(list_nested(self.items.into_iter())?) + Ok(seq_nested(self.items.into_iter())?) } } @@ -277,7 +277,7 @@ impl ser::SerializeTupleVariant for SeqSerializer { } fn end(self) -> Result { - Ok(list_nested(self.items.into_iter())?) + Ok(seq_nested(self.items.into_iter())?) } } @@ -334,7 +334,7 @@ impl ser::SerializeStruct for StructSerializer { } fn end(self) -> Result> { - Ok(list([string(self.name)?, dict(self.fields.into_iter())?])?) + Ok(seq([string(self.name)?, dict(self.fields.into_iter())?])?) } } @@ -357,7 +357,7 @@ impl ser::SerializeStructVariant for StructVariantSerializer { } fn end(self) -> Result> { - Ok(list([ + Ok(seq([ string_owned(format!("{}.{}", self.name, self.variant))?, dict(self.fields.into_iter())?, ])?)