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,
|
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};
|
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.
|
/// Decodes a nettext string into the term it represents.
|
||||||
pub fn decode(input: &[u8]) -> std::result::Result<Term<'_, '_>, DecodeError<'_>> {
|
pub fn decode(input: &[u8]) -> std::result::Result<Term<'_, '_>, DecodeError<'_>> {
|
||||||
let (rest, term) = decode_term(input)?;
|
let (rest, term) = decode_term(input)?;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::dec::debug;
|
||||||
|
|
||||||
/// The type of errors returned by helper functions on `Term`
|
/// The type of errors returned by helper functions on `Term`
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TypeError {
|
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;
|
use crate::crypto;
|
||||||
pub use decode::*;
|
pub use decode::*;
|
||||||
pub use error::TypeError;
|
pub use error::*;
|
||||||
|
|
||||||
/// A parsed nettext term, with many helpers for destructuring
|
/// 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
|
/// is returned by one of the helper functions, or 'static when first returned from
|
||||||
/// `decode()`
|
/// `decode()`
|
||||||
#[derive(Eq, PartialEq, Debug)]
|
#[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)]
|
#[derive(Eq, PartialEq, Clone)]
|
||||||
pub(crate) enum AnyTerm<'a, 'b> {
|
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 {
|
match &self {
|
||||||
AnyTerm::Str(s) => AnyTerm::Str(s),
|
AnyTerm::Str(s) => AnyTerm::Str(s),
|
||||||
AnyTerm::Dict(r, d) => AnyTerm::DictRef(r, d),
|
AnyTerm::Dict(r, d) => AnyTerm::DictRef(r, d),
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::borrow::{Cow, Borrow};
|
|
||||||
|
|
||||||
use crate::dec::{self, decode};
|
use crate::dec::{self, decode};
|
||||||
use crate::{is_string_char, is_whitespace};
|
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 {
|
pub enum Error {
|
||||||
Message(String),
|
Message(String),
|
||||||
Encode(enc::Error),
|
Encode(enc::Error),
|
||||||
|
Decode(String),
|
||||||
Type(dec::TypeError),
|
Type(dec::TypeError),
|
||||||
|
ParseInt(std::num::ParseIntError),
|
||||||
|
ParseFloat(std::num::ParseFloatError),
|
||||||
|
Utf8(std::string::FromUtf8Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<enc::Error> for Error {
|
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 {
|
impl From<dec::TypeError> for Error {
|
||||||
fn from(e: dec::TypeError) -> Self {
|
fn from(e: dec::TypeError) -> Self {
|
||||||
Error::Type(e)
|
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 {
|
impl de::Error for Error {
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
fn custom<T: Display>(msg: T) -> Self {
|
||||||
Error::Message(msg.to_string())
|
Error::Message(msg.to_string())
|
||||||
|
@ -43,7 +71,11 @@ impl Display for Error {
|
||||||
match self {
|
match self {
|
||||||
Error::Message(msg) => formatter.write_str(msg),
|
Error::Message(msg) => formatter.write_str(msg),
|
||||||
Error::Encode(err) => write!(formatter, "Encode: {}", err),
|
Error::Encode(err) => write!(formatter, "Encode: {}", err),
|
||||||
|
Error::Decode(err) => write!(formatter, "Decode: {}", err),
|
||||||
Error::Type(err) => write!(formatter, "Type: {}", 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 error;
|
||||||
mod ser;
|
mod ser;
|
||||||
|
|
||||||
//pub use de::{from_str, Deserializer};
|
pub use de::{from_bytes, Deserializer};
|
||||||
pub use error::{Error, Result};
|
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 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>>
|
pub fn to_bytes<T>(value: &T) -> Result<Vec<u8>>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
|
@ -94,7 +101,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
||||||
where
|
where
|
||||||
T: ?Sized + Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(self)
|
Ok(value.serialize(self)?.nested())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<Self::Ok> {
|
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> {
|
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(
|
fn serialize_tuple_struct(
|
||||||
|
@ -150,11 +159,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleStruct> {
|
) -> Result<Self::SerializeTupleStruct> {
|
||||||
let mut items = Vec::with_capacity(len + 1);
|
let mut items = Vec::with_capacity(len + 1);
|
||||||
items.push(string(name)?);
|
items.push(string(name)?);
|
||||||
Ok(SeqSerializer {
|
Ok(SeqSerializer { items })
|
||||||
items,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
fn serialize_tuple_variant(
|
||||||
|
@ -164,11 +171,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant> {
|
) -> Result<Self::SerializeTupleVariant> {
|
||||||
let mut items = Vec::with_capacity(len + 1);
|
let mut items = Vec::with_capacity(len + 1);
|
||||||
items.push(string_owned(format!("{}.{}", name, variant))?);
|
items.push(string_owned(format!("{}.{}", name, variant))?);
|
||||||
Ok(SeqSerializer {
|
Ok(SeqSerializer { items })
|
||||||
items,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
|
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||||
|
@ -360,7 +365,7 @@ impl<'a> ser::SerializeStructVariant for StructVariantSerializer {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_struct() {
|
fn test_struct() {
|
||||||
|
@ -430,8 +435,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dict() {
|
fn test_dict() {
|
||||||
let mut d = HashMap::new();
|
let mut d = HashMap::new();
|
||||||
d.insert("hello", "world");
|
d.insert("hello", "world");
|
||||||
d.insert("dont", "panic");
|
d.insert("dont", "panic");
|
||||||
let expected = br#"{
|
let expected = br#"{
|
||||||
ZG9udA = cGFuaWM,
|
ZG9udA = cGFuaWM,
|
||||||
aGVsbG8 = d29ybGQ,
|
aGVsbG8 = d29ybGQ,
|
||||||
|
@ -439,8 +444,8 @@ mod tests {
|
||||||
assert_eq!(&to_bytes(&d).unwrap(), expected);
|
assert_eq!(&to_bytes(&d).unwrap(), expected);
|
||||||
|
|
||||||
let mut d = HashMap::new();
|
let mut d = HashMap::new();
|
||||||
d.insert(12, vec![42, 125]);
|
d.insert(12, vec![42, 125]);
|
||||||
d.insert(33, vec![19, 22, 21]);
|
d.insert(33, vec![19, 22, 21]);
|
||||||
let expected = br#"{
|
let expected = br#"{
|
||||||
12 = 42 125,
|
12 = 42 125,
|
||||||
33 = 19 22 21,
|
33 = 19 22 21,
|
||||||
|
|
Loading…
Reference in a new issue