Change encode to be a method of Term

This commit is contained in:
Alex 2022-11-18 12:53:14 +01:00
parent bc319d3089
commit 7cb5ff2fc2
Signed by: lx
GPG key ID: 0E496D15096376BE
2 changed files with 73 additions and 70 deletions

View file

@ -46,7 +46,7 @@ impl<'a, 'b> Encode for dec::Term<'a, 'b> {
/// ``` /// ```
/// use nettext::enc::*; /// use nettext::enc::*;
/// ///
/// assert_eq!(encode(string("Hello world .").unwrap()), b"Hello world ."); /// assert_eq!(string("Hello world .").unwrap().encode(), b"Hello world .");
/// ``` /// ```
pub fn string(s: &str) -> Result<'_> { pub fn string(s: &str) -> Result<'_> {
for c in s.as_bytes().iter() { for c in s.as_bytes().iter() {
@ -62,7 +62,7 @@ pub fn string(s: &str) -> Result<'_> {
/// ``` /// ```
/// use nettext::enc::*; /// use nettext::enc::*;
/// ///
/// assert_eq!(encode(raw(b"Hello { a = b, c = d} .").unwrap()), b"Hello { a = b, c = d} ."); /// assert_eq!(raw(b"Hello { a = b, c = d} .").unwrap().encode(), b"Hello { a = b, c = d} .");
/// ``` /// ```
pub fn raw(bytes: &[u8]) -> Result<'_> { pub fn raw(bytes: &[u8]) -> Result<'_> {
if decode(bytes).is_err() { if decode(bytes).is_err() {
@ -76,10 +76,10 @@ pub fn raw(bytes: &[u8]) -> Result<'_> {
/// ``` /// ```
/// use nettext::enc::*; /// use nettext::enc::*;
/// ///
/// assert_eq!(encode(list([ /// assert_eq!(list([
/// string("Hello").unwrap(), /// string("Hello").unwrap(),
/// string("world").unwrap() /// string("world").unwrap()
/// ]).unwrap()), b"Hello world"); /// ]).unwrap().encode(), b"Hello world");
/// ``` /// ```
pub fn list<'a, I: IntoIterator<Item = Term<'a>>>(terms: I) -> Result<'a> { pub fn list<'a, I: IntoIterator<Item = Term<'a>>>(terms: I) -> Result<'a> {
let mut tmp = Vec::with_capacity(8); let mut tmp = Vec::with_capacity(8);
@ -97,10 +97,10 @@ pub fn list<'a, I: IntoIterator<Item = Term<'a>>>(terms: I) -> Result<'a> {
/// ``` /// ```
/// use nettext::enc::*; /// use nettext::enc::*;
/// ///
/// assert_eq!(encode(dict([ /// assert_eq!(dict([
/// ("a", string("Hello").unwrap()), /// ("a", string("Hello").unwrap()),
/// ("b", string("world").unwrap()) /// ("b", string("world").unwrap())
/// ])), b"{\n a = Hello,\n b = world,\n}"); /// ]).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) -> Term<'a> {
let mut tmp = HashMap::new(); let mut tmp = HashMap::new();
@ -118,7 +118,7 @@ pub fn dict<'a, I: IntoIterator<Item = (&'a str, Term<'a>)>>(pairs: I) -> Term<'
/// ``` /// ```
/// use nettext::enc::*; /// use nettext::enc::*;
/// ///
/// assert_eq!(encode(bytes(b"hello, world!")), b"aGVsbG8sIHdvcmxkIQ"); /// assert_eq!(bytes(b"hello, world!").encode(), b"aGVsbG8sIHdvcmxkIQ");
/// ``` /// ```
pub fn bytes(bytes: &[u8]) -> Term<'static> { pub fn bytes(bytes: &[u8]) -> Term<'static> {
Term(T::OwnedStr( Term(T::OwnedStr(
@ -176,7 +176,7 @@ impl<'a> Term<'a> {
/// ``` /// ```
/// use nettext::enc::*; /// use nettext::enc::*;
/// ///
/// assert_eq!(encode(list([string("hello").unwrap(), string("world").unwrap()]).unwrap().nested()), b"{ . = hello world }"); /// assert_eq!(list([string("hello").unwrap(), string("world").unwrap()]).unwrap().nested().encode(), b"{ . = hello world }");
/// ``` /// ```
#[must_use] #[must_use]
pub fn nested(self) -> Term<'a> { pub fn nested(self) -> Term<'a> {
@ -186,15 +186,18 @@ impl<'a> Term<'a> {
// ---- encoding function ---- // ---- encoding function ----
impl<'a> Term<'a> {
/// Generate the nettext representation of a term /// Generate the nettext representation of a term
pub fn encode(t: Term<'_>) -> Vec<u8> { pub fn encode(self) -> Vec<u8> {
let mut buf = Vec::with_capacity(128); let mut buf = Vec::with_capacity(128);
encode_aux(&mut buf, t.0, 0, true); self.0.encode_aux(&mut buf, 0, true);
buf buf
} }
}
fn encode_aux(buf: &mut Vec<u8>, term: T<'_>, indent: usize, is_toplevel: bool) { impl<'a> T<'a> {
match term { fn encode_aux(self, buf: &mut Vec<u8>, indent: usize, is_toplevel: bool) {
match self {
T::Str(s) => buf.extend_from_slice(s), T::Str(s) => buf.extend_from_slice(s),
T::OwnedStr(s) => buf.extend_from_slice(&s), T::OwnedStr(s) => buf.extend_from_slice(&s),
T::Dict(mut d) => { T::Dict(mut d) => {
@ -205,7 +208,7 @@ fn encode_aux(buf: &mut Vec<u8>, term: T<'_>, indent: usize, is_toplevel: bool)
let (k, v) = d.into_iter().next().unwrap(); let (k, v) = d.into_iter().next().unwrap();
buf.extend_from_slice(k); buf.extend_from_slice(k);
buf.extend_from_slice(b" = "); buf.extend_from_slice(b" = ");
encode_aux(buf, v, indent + 2, false); v.encode_aux(buf, indent + 2, false);
buf.extend_from_slice(b" }"); buf.extend_from_slice(b" }");
} else { } else {
buf.extend_from_slice(b"{\n"); buf.extend_from_slice(b"{\n");
@ -219,7 +222,7 @@ fn encode_aux(buf: &mut Vec<u8>, term: T<'_>, indent: usize, is_toplevel: bool)
} }
buf.extend_from_slice(k); buf.extend_from_slice(k);
buf.extend_from_slice(b" = "); buf.extend_from_slice(b" = ");
encode_aux(buf, v, indent2, false); v.encode_aux(buf, indent2, false);
buf.extend_from_slice(b",\n"); buf.extend_from_slice(b",\n");
} }
for _ in 0..indent { for _ in 0..indent {
@ -239,7 +242,8 @@ fn encode_aux(buf: &mut Vec<u8>, term: T<'_>, indent: usize, is_toplevel: bool)
} else if i > 0 { } else if i > 0 {
buf.push(b' '); buf.push(b' ');
} }
encode_aux(buf, v, indent2, is_toplevel); v.encode_aux(buf, indent2, is_toplevel);
}
} }
} }
} }
@ -266,7 +270,7 @@ mod tests {
from = jxx, from = jxx,
subject = hello, subject = hello,
}"; }";
let enc = encode(input); let enc = input.encode();
eprintln!("{}", std::str::from_utf8(&enc).unwrap()); eprintln!("{}", std::str::from_utf8(&enc).unwrap());
eprintln!("{}", std::str::from_utf8(&expected[..]).unwrap()); eprintln!("{}", std::str::from_utf8(&expected[..]).unwrap());
assert_eq!(&enc, &expected[..]); assert_eq!(&enc, &expected[..]);
@ -282,7 +286,6 @@ mod tests {
.is_err()); .is_err());
assert_eq!( assert_eq!(
encode(
list([ list([
string("a").unwrap(), string("a").unwrap(),
string("b").unwrap(), string("b").unwrap(),
@ -291,7 +294,7 @@ mod tests {
.nested() .nested()
]) ])
.unwrap() .unwrap()
), .encode(),
b"a b { . = c d }" b"a b { . = c d }"
); );
} }

View file

@ -8,7 +8,7 @@
//! let keypair = crypto::generate_keypair(); //! let keypair = crypto::generate_keypair();
//! //!
//! // Encode a fist object that represents a payload that will be hashed and signed //! // Encode a fist object that represents a payload that will be hashed and signed
//! let text1 = encode(list([ //! let text1 = list([
//! string("CALL").unwrap(), //! string("CALL").unwrap(),
//! string("myfunction").unwrap(), //! string("myfunction").unwrap(),
//! dict([ //! dict([
@ -18,18 +18,18 @@
//! ("d", bytes_split(&((0..128u8).collect::<Vec<_>>()))), //! ("d", bytes_split(&((0..128u8).collect::<Vec<_>>()))),
//! ]), //! ]),
//! keypair.public.term().unwrap(), //! keypair.public.term().unwrap(),
//! ]).unwrap()); //! ]).unwrap().encode();
//! eprintln!("{}", std::str::from_utf8(&text1).unwrap()); //! eprintln!("{}", std::str::from_utf8(&text1).unwrap());
//! //!
//! let hash = crypto::Blake2Sum::compute(&text1); //! let hash = crypto::Blake2Sum::compute(&text1);
//! let sign = keypair.sign(&text1); //! let sign = keypair.sign(&text1);
//! //!
//! // Encode a second object that represents the signed and hashed payload //! // Encode a second object that represents the signed and hashed payload
//! let text2 = encode(dict([ //! let text2 = dict([
//! ("hash", hash.term().unwrap()), //! ("hash", hash.term().unwrap()),
//! ("signature", sign.term().unwrap()), //! ("signature", sign.term().unwrap()),
//! ("payload", raw(&text1).unwrap()), //! ("payload", raw(&text1).unwrap()),
//! ])); //! ]).encode();
//! eprintln!("{}", std::str::from_utf8(&text2).unwrap()); //! eprintln!("{}", std::str::from_utf8(&text2).unwrap());
//! //!
//! // Decode and check everything is fine //! // Decode and check everything is fine