Deserializer seems to work a bit
This commit is contained in:
parent
4b8555711e
commit
1bcefaa1ae
8 changed files with 595 additions and 57 deletions
|
@ -8,43 +8,11 @@ use nom::{
|
|||
IResult, InputLength,
|
||||
};
|
||||
|
||||
use crate::dec::{debug, AnyTerm, NonListTerm, Term};
|
||||
use crate::dec::{AnyTerm, DecodeError, NonListTerm, Term};
|
||||
use crate::{is_string_char, is_whitespace, DICT_ASSIGN, DICT_CLOSE, DICT_DELIM, DICT_OPEN};
|
||||
|
||||
// ----
|
||||
|
||||
/// The error kind returned by the `decode` function.
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum DecodeError<'a> {
|
||||
/// Indicates that there is trailing garbage at the end of the decoded string
|
||||
Garbage(&'a [u8]),
|
||||
/// Indicates that the entered string does not represent a complete nettext term
|
||||
IncompleteInput,
|
||||
/// Indicates a syntax error in the decoded term
|
||||
NomError(&'a [u8], nom::error::ErrorKind),
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for DecodeError<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
DecodeError::Garbage(g) => write!(f, "Garbage: `{}`", debug(g)),
|
||||
DecodeError::IncompleteInput => write!(f, "Incomplete input"),
|
||||
DecodeError::NomError(s, e) => write!(f, "Nom: {:?}, at: `{}`", e, debug(s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<nom::Err<nom::error::Error<&'a [u8]>>> for DecodeError<'a> {
|
||||
fn from(e: nom::Err<nom::error::Error<&'a [u8]>>) -> DecodeError<'a> {
|
||||
match e {
|
||||
nom::Err::Incomplete(_) => DecodeError::IncompleteInput,
|
||||
nom::Err::Error(e) | nom::Err::Failure(e) => DecodeError::NomError(e.input, e.code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
/// Decodes a nettext string into the term it represents.
|
||||
pub fn decode(input: &[u8]) -> std::result::Result<Term<'_, '_>, DecodeError<'_>> {
|
||||
let (rest, term) = decode_term(input)?;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::fmt;
|
||||
|
||||
use crate::dec::debug;
|
||||
|
||||
/// The type of errors returned by helper functions on `Term`
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypeError {
|
||||
|
@ -32,3 +34,41 @@ impl std::fmt::Display for TypeError {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
/// The error kind returned by the `decode` function.
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum DecodeError<'a> {
|
||||
/// Indicates that there is trailing garbage at the end of the decoded string
|
||||
Garbage(&'a [u8]),
|
||||
/// Indicates that the entered string does not represent a complete nettext term
|
||||
IncompleteInput,
|
||||
/// Indicates a syntax error in the decoded term
|
||||
NomError(&'a [u8], nom::error::ErrorKind),
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Display for DecodeError<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
DecodeError::Garbage(g) => write!(f, "Garbage: `{}`", debug(g)),
|
||||
DecodeError::IncompleteInput => write!(f, "Incomplete input"),
|
||||
DecodeError::NomError(s, e) => write!(f, "Nom: {:?}, at: `{}`", e, debug(s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for DecodeError<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
std::fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<nom::Err<nom::error::Error<&'a [u8]>>> for DecodeError<'a> {
|
||||
fn from(e: nom::Err<nom::error::Error<&'a [u8]>>) -> DecodeError<'a> {
|
||||
match e {
|
||||
nom::Err::Incomplete(_) => DecodeError::IncompleteInput,
|
||||
nom::Err::Error(e) | nom::Err::Failure(e) => DecodeError::NomError(e.input, e.code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
|||
|
||||
use crate::crypto;
|
||||
pub use decode::*;
|
||||
pub use error::TypeError;
|
||||
pub use error::*;
|
||||
|
||||
/// A parsed nettext term, with many helpers for destructuring
|
||||
///
|
||||
|
@ -17,7 +17,7 @@ pub use error::TypeError;
|
|||
/// is returned by one of the helper functions, or 'static when first returned from
|
||||
/// `decode()`
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct Term<'a, 'b>(AnyTerm<'a, 'b>);
|
||||
pub struct Term<'a, 'b>(pub(crate) AnyTerm<'a, 'b>);
|
||||
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
pub(crate) enum AnyTerm<'a, 'b> {
|
||||
|
@ -501,7 +501,7 @@ impl<'a, 'b> AnyTerm<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn mkref(&self) -> AnyTerm<'a, '_> {
|
||||
pub(crate) fn mkref(&self) -> AnyTerm<'a, '_> {
|
||||
match &self {
|
||||
AnyTerm::Str(s) => AnyTerm::Str(s),
|
||||
AnyTerm::Dict(r, d) => AnyTerm::DictRef(r, d),
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
mod error;
|
||||
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::collections::HashMap;
|
||||
use std::borrow::{Cow, Borrow};
|
||||
|
||||
use crate::dec::{self, decode};
|
||||
use crate::{is_string_char, is_whitespace};
|
||||
|
|
493
src/serde/de.rs
Normal file
493
src/serde/de.rs
Normal file
|
@ -0,0 +1,493 @@
|
|||
use std::collections::{hash_map, HashMap};
|
||||
|
||||
use serde::de::{
|
||||
self, DeserializeSeed, EnumAccess, Error as DeError, MapAccess, SeqAccess, VariantAccess,
|
||||
Visitor,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::dec::debug as fmtdebug;
|
||||
use crate::dec::*;
|
||||
use crate::serde::error::{Error, Result};
|
||||
|
||||
pub struct Deserializer<'de, 'a>(Term<'de, 'a>);
|
||||
|
||||
impl<'de, 'a> Deserializer<'de, 'a> {
|
||||
pub fn from_term(input: &'a Term<'de, 'a>) -> Deserializer<'de, 'a> {
|
||||
if let Ok(nested) = input.nested() {
|
||||
Deserializer(nested)
|
||||
} else {
|
||||
Deserializer(Term(input.0.mkref()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result<T>
|
||||
where
|
||||
T: Deserialize<'a>,
|
||||
{
|
||||
let term = decode(s)?;
|
||||
let mut deserializer = Deserializer::from_term(&term);
|
||||
Ok(T::deserialize(&mut deserializer)?)
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
Err(Error::custom("derialize_any not supported"))
|
||||
}
|
||||
|
||||
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let value = match self.0.string()? {
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => return Err(Error::custom("Invalid boolean litteral")),
|
||||
};
|
||||
visitor.visit_bool(value)
|
||||
}
|
||||
|
||||
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i8(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i16(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i32(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i64(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u8(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u16(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u32(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u64(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_f32(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_f64(self.0.string()?.parse()?)
|
||||
}
|
||||
|
||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let s = String::from_utf8(self.0.bytes()?)?;
|
||||
let mut chars = s.chars();
|
||||
let c = chars
|
||||
.next()
|
||||
.ok_or(Error::custom("invalid char: empty string"))?;
|
||||
if chars.next().is_some() {
|
||||
Err(Error::custom("invalid char: too many chars"))
|
||||
} else {
|
||||
visitor.visit_char(c)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let s = String::from_utf8(self.0.bytes()?)?;
|
||||
visitor.visit_string(s)
|
||||
}
|
||||
|
||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_str(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_byte_buf(self.0.bytes()?)
|
||||
}
|
||||
|
||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_byte_buf(self.0.bytes()?)
|
||||
}
|
||||
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.0.dict_of::<0, &[u8]>([], false).is_ok() {
|
||||
visitor.visit_none()
|
||||
} else {
|
||||
visitor.visit_some(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.0.dict_of::<0, &[u8]>([], false).is_ok() {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
Err(Error::custom(format!(
|
||||
"Expected unit, got: `{}`",
|
||||
fmtdebug(self.0.raw())
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.0.string()? == name {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
Err(Error::custom(format!(
|
||||
"Expected {}, got: `{}`",
|
||||
name,
|
||||
fmtdebug(self.0.raw())
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let [variant, args] = self.0.list_of_first()?;
|
||||
if variant.string()? == name {
|
||||
visitor.visit_newtype_struct(&mut Deserializer(args))
|
||||
} else {
|
||||
Err(Error::custom(format!(
|
||||
"Expected {}, got: `{}`",
|
||||
name,
|
||||
fmtdebug(variant.raw())
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_seq(&mut Seq(&self.0.list()))
|
||||
}
|
||||
|
||||
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_seq(&mut Seq(&self.0.list()))
|
||||
}
|
||||
|
||||
fn deserialize_tuple_struct<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
_len: usize,
|
||||
visitor: V,
|
||||
) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let [variant, args] = self.0.list_of_first()?;
|
||||
if variant.string()? == name {
|
||||
visitor.visit_seq(&mut Seq(&args.list()))
|
||||
} else {
|
||||
Err(Error::custom(format!(
|
||||
"Expected {}, got: `{}`",
|
||||
name,
|
||||
fmtdebug(variant.raw())
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(&mut Dict::from_term(&self.0)?)
|
||||
}
|
||||
|
||||
fn deserialize_struct<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let [variant, data] = self.0.list_of()?;
|
||||
if variant.string()? != name {
|
||||
return Err(Error::custom(format!(
|
||||
"Expected {}, got: `{}`",
|
||||
name,
|
||||
fmtdebug(variant.raw())
|
||||
)));
|
||||
}
|
||||
|
||||
Deserializer(data).deserialize_map(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_enum(Enum(&self.0))
|
||||
}
|
||||
|
||||
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let s = self.0.string()?;
|
||||
match s.split_once('.') {
|
||||
Some((_a, b)) => visitor.visit_borrowed_str(b),
|
||||
None => visitor.visit_borrowed_str(s),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Seq<'de, 'a>(&'a [Term<'de, 'a>]);
|
||||
|
||||
impl<'de, 'a> SeqAccess<'de> for &'a mut Seq<'de, 'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
// Check if there are no more elements.
|
||||
if self.0.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
let first = Term(self.0[0].0.mkref());
|
||||
self.0 = &self.0[1..];
|
||||
|
||||
seed.deserialize(&mut Deserializer(first)).map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dict<'de, 'a>(
|
||||
&'a HashMap<&'de [u8], AnyTerm<'de, 'a>>,
|
||||
Option<&'de [u8]>,
|
||||
hash_map::Keys<'a, &'de [u8], AnyTerm<'de, 'a>>,
|
||||
);
|
||||
|
||||
impl<'de, 'a> Dict<'de, 'a> {
|
||||
fn from_term(t: &'a Term<'de, 'a>) -> Result<Dict<'de, 'a>> {
|
||||
match t.0.mkref() {
|
||||
AnyTerm::DictRef(_, d) => Ok(Dict(d, None, d.keys())),
|
||||
_ => Err(Error::custom("expected a DICT")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a> MapAccess<'de> for &'a mut Dict<'de, 'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
|
||||
where
|
||||
K: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.2.next() {
|
||||
None => Ok(None),
|
||||
Some(k) => {
|
||||
self.1 = Some(k);
|
||||
seed.deserialize(&mut Deserializer(Term(AnyTerm::Str(k))))
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
let k = self.1.ok_or(Error::custom("invald mapaccess order"))?;
|
||||
let v = self
|
||||
.0
|
||||
.get(k)
|
||||
.ok_or(Error::custom("invald mapaccess order"))?;
|
||||
seed.deserialize(&mut Deserializer(Term(v.mkref())))
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
struct Enum<'de, 'a>(&'a Term<'de, 'a>);
|
||||
|
||||
impl<'de, 'a> EnumAccess<'de> for Enum<'de, 'a> {
|
||||
type Error = Error;
|
||||
type Variant = Self;
|
||||
|
||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
let value = seed.deserialize(&mut Deserializer::from_term(&self.0.list()[0]))?;
|
||||
Ok((value, self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a> VariantAccess<'de> for Enum<'de, 'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn unit_variant(self) -> Result<()> {
|
||||
if self.0.list().len() > 1 {
|
||||
Err(Error::custom("Spurrious data in unit variant"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
let [_, rest] = self.0.list_of_first()?;
|
||||
seed.deserialize(&mut Deserializer::from_term(&rest))
|
||||
}
|
||||
|
||||
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let [_, rest] = self.0.list_of_first()?;
|
||||
visitor.visit_seq(&mut Seq(&rest.list()))
|
||||
}
|
||||
|
||||
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let [_, rest] = self.0.list_of_first()?;
|
||||
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");
|
||||
}
|
||||
}
|
|
@ -11,7 +11,11 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||
pub enum Error {
|
||||
Message(String),
|
||||
Encode(enc::Error),
|
||||
Decode(String),
|
||||
Type(dec::TypeError),
|
||||
ParseInt(std::num::ParseIntError),
|
||||
ParseFloat(std::num::ParseFloatError),
|
||||
Utf8(std::string::FromUtf8Error),
|
||||
}
|
||||
|
||||
impl From<enc::Error> for Error {
|
||||
|
@ -20,6 +24,12 @@ impl From<enc::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<dec::DecodeError<'a>> for Error {
|
||||
fn from(e: dec::DecodeError) -> Self {
|
||||
Error::Decode(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dec::TypeError> for Error {
|
||||
fn from(e: dec::TypeError) -> Self {
|
||||
Error::Type(e)
|
||||
|
@ -32,6 +42,24 @@ impl ser::Error for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<std::num::ParseIntError> for Error {
|
||||
fn from(x: std::num::ParseIntError) -> Error {
|
||||
Error::ParseInt(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::num::ParseFloatError> for Error {
|
||||
fn from(x: std::num::ParseFloatError) -> Error {
|
||||
Error::ParseFloat(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::string::FromUtf8Error> for Error {
|
||||
fn from(x: std::string::FromUtf8Error) -> Error {
|
||||
Error::Utf8(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error::Message(msg.to_string())
|
||||
|
@ -43,7 +71,11 @@ impl Display for Error {
|
|||
match self {
|
||||
Error::Message(msg) => formatter.write_str(msg),
|
||||
Error::Encode(err) => write!(formatter, "Encode: {}", err),
|
||||
Error::Decode(err) => write!(formatter, "Decode: {}", err),
|
||||
Error::Type(err) => write!(formatter, "Type: {}", err),
|
||||
Error::ParseInt(err) => write!(formatter, "Parse (int): {}", err),
|
||||
Error::ParseFloat(err) => write!(formatter, "Parse (float): {}", err),
|
||||
Error::Utf8(err) => write!(formatter, "Invalid UTF-8 byte sequnence: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//mod de;
|
||||
mod de;
|
||||
mod error;
|
||||
mod ser;
|
||||
|
||||
//pub use de::{from_str, Deserializer};
|
||||
pub use de::{from_bytes, Deserializer};
|
||||
pub use error::{Error, Result};
|
||||
pub use ser::{to_bytes, Serializer};
|
||||
pub use ser::{to_bytes, to_term, Serializer};
|
||||
|
|
|
@ -6,6 +6,13 @@ use serde::ser::Error as SerError;
|
|||
|
||||
pub struct Serializer;
|
||||
|
||||
pub fn to_term<T>(value: &T) -> Result<Term<'static>>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Ok(value.serialize(&mut Serializer)?)
|
||||
}
|
||||
|
||||
pub fn to_bytes<T>(value: &T) -> Result<Vec<u8>>
|
||||
where
|
||||
T: Serialize,
|
||||
|
@ -94,7 +101,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
|||
where
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
Ok(value.serialize(self)?.nested())
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok> {
|
||||
|
@ -142,7 +149,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
|||
}
|
||||
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
|
||||
Ok(SeqSerializer { items: Vec::with_capacity(len) })
|
||||
Ok(SeqSerializer {
|
||||
items: Vec::with_capacity(len),
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
|
@ -150,11 +159,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
|||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct> {
|
||||
let mut items = Vec::with_capacity(len + 1);
|
||||
items.push(string(name)?);
|
||||
Ok(SeqSerializer {
|
||||
items,
|
||||
})
|
||||
let mut items = Vec::with_capacity(len + 1);
|
||||
items.push(string(name)?);
|
||||
Ok(SeqSerializer { items })
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
|
@ -164,11 +171,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
|||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant> {
|
||||
let mut items = Vec::with_capacity(len + 1);
|
||||
items.push(string_owned(format!("{}.{}", name, variant))?);
|
||||
Ok(SeqSerializer {
|
||||
items,
|
||||
})
|
||||
let mut items = Vec::with_capacity(len + 1);
|
||||
items.push(string_owned(format!("{}.{}", name, variant))?);
|
||||
Ok(SeqSerializer { items })
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||
|
@ -360,7 +365,7 @@ impl<'a> ser::SerializeStructVariant for StructVariantSerializer {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn test_struct() {
|
||||
|
@ -430,8 +435,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_dict() {
|
||||
let mut d = HashMap::new();
|
||||
d.insert("hello", "world");
|
||||
d.insert("dont", "panic");
|
||||
d.insert("hello", "world");
|
||||
d.insert("dont", "panic");
|
||||
let expected = br#"{
|
||||
ZG9udA = cGFuaWM,
|
||||
aGVsbG8 = d29ybGQ,
|
||||
|
@ -439,8 +444,8 @@ mod tests {
|
|||
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]);
|
||||
d.insert(12, vec![42, 125]);
|
||||
d.insert(33, vec![19, 22, 21]);
|
||||
let expected = br#"{
|
||||
12 = 42 125,
|
||||
33 = 19 22 21,
|
||||
|
|
Loading…
Reference in a new issue