use form_urlencoded::parse;
use form_urlencoded::Parse as UrlEncodedParse;
use serde::de::value::MapDeserializer;
use serde::de::Error as de_Error;
use serde::de::{self, IntoDeserializer};
use serde::forward_to_deserialize_any;
use std::borrow::Cow;
use std::io::Read;
#[doc(inline)]
pub use serde::de::value::Error;
pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result<T, Error>
where
T: de::Deserialize<'de>,
{
T::deserialize(Deserializer::new(parse(input)))
}
pub fn from_str<'de, T>(input: &'de str) -> Result<T, Error>
where
T: de::Deserialize<'de>,
{
from_bytes(input.as_bytes())
}
pub fn from_reader<T, R>(mut reader: R) -> Result<T, Error>
where
T: de::DeserializeOwned,
R: Read,
{
let mut buf = vec![];
reader.read_to_end(&mut buf).map_err(|e| {
de::Error::custom(format_args!("could not read input: {}", e))
})?;
from_bytes(&buf)
}
pub struct Deserializer<'de> {
inner: MapDeserializer<'de, PartIterator<'de>, Error>,
}
impl<'de> Deserializer<'de> {
pub fn new(parser: UrlEncodedParse<'de>) -> Self {
Deserializer {
inner: MapDeserializer::new(PartIterator(parser)),
}
}
}
impl<'de> de::Deserializer<'de> for Deserializer<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
self.deserialize_map(visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_map(self.inner)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_seq(self.inner)
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
self.inner.end()?;
visitor.visit_unit()
}
forward_to_deserialize_any! {
bool
u8
u16
u32
u64
i8
i16
i32
i64
f32
f64
char
str
string
option
bytes
byte_buf
unit_struct
newtype_struct
tuple_struct
struct
identifier
tuple
enum
ignored_any
}
}
struct PartIterator<'de>(UrlEncodedParse<'de>);
impl<'de> Iterator for PartIterator<'de> {
type Item = (Part<'de>, Part<'de>);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(k, v)| (Part(k), Part(v)))
}
}
struct Part<'de>(Cow<'de, str>);
impl<'de> IntoDeserializer<'de> for Part<'de> {
type Deserializer = Self;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
macro_rules! forward_parsed_value {
($($ty:ident => $method:ident,)*) => {
$(
fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor<'de>
{
match self.0.parse::<$ty>() {
Ok(val) => val.into_deserializer().$method(visitor),
Err(e) => Err(de::Error::custom(e))
}
}
)*
}
}
impl<'de> de::Deserializer<'de> for Part<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
match self.0 {
Cow::Borrowed(value) => visitor.visit_borrowed_str(value),
Cow::Owned(value) => visitor.visit_string(value),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_some(self)
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_enum(ValueEnumAccess(self.0))
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
match self.0 {
Cow::Borrowed(borrowed) => visitor.visit_seq(CommaSeparatedBorrowed::new(borrowed)),
Cow::Owned(owned) => visitor.visit_seq(CommaSeparatedOwned::new(owned.rsplit(',').map(str::to_string).collect()))
}
}
forward_to_deserialize_any! {
char
str
string
unit
bytes
byte_buf
unit_struct
tuple_struct
struct
identifier
tuple
ignored_any
map
}
forward_parsed_value! {
bool => deserialize_bool,
u8 => deserialize_u8,
u16 => deserialize_u16,
u32 => deserialize_u32,
u64 => deserialize_u64,
i8 => deserialize_i8,
i16 => deserialize_i16,
i32 => deserialize_i32,
i64 => deserialize_i64,
f32 => deserialize_f32,
f64 => deserialize_f64,
}
}
struct CommaSeparatedBorrowed<'de> {
de: &'de str
}
impl<'de> CommaSeparatedBorrowed<'de> {
fn new(de: &'de str) -> CommaSeparatedBorrowed<'de>{
CommaSeparatedBorrowed {
de
}
}
fn get_next_comma_position(&self) -> Option<usize> {
self.de.chars().position(|x| x == ',')
}
fn get_slice(&mut self) -> &'de str {
match self.get_next_comma_position() {
Some(pos) => {
let res = &self.de[..pos];
self.de = &self.de[pos+1..];
res
}
None => {
let res = &self.de[..];
self.de = "";
res
}
}
}
}
impl<'de> de::SeqAccess<'de> for CommaSeparatedBorrowed<'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>
{
if self.de.is_empty() {
return Ok(None)
}
seed.deserialize(Part(Cow::Borrowed(self.get_slice())).into_deserializer()).map(Some)
}
}
struct CommaSeparatedOwned {
de: Vec<String>
}
impl CommaSeparatedOwned {
pub fn new(de: Vec<String>) -> CommaSeparatedOwned {
CommaSeparatedOwned {
de
}
}
}
impl<'de> de::SeqAccess<'de> for CommaSeparatedOwned {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>
{
match self.de.pop() {
Some(value) => {
seed.deserialize(Part(Cow::Owned(value)).into_deserializer()).map(Some)
},
None => Ok(None)
}
}
}
struct ValueEnumAccess<'de>(Cow<'de, str>);
impl<'de> de::EnumAccess<'de> for ValueEnumAccess<'de> {
type Error = Error;
type Variant = UnitOnlyVariantAccess;
fn variant_seed<V>(
self,
seed: V,
) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: de::DeserializeSeed<'de>,
{
let variant = seed.deserialize(self.0.into_deserializer())?;
Ok((variant, UnitOnlyVariantAccess))
}
}
struct UnitOnlyVariantAccess;
impl<'de> de::VariantAccess<'de> for UnitOnlyVariantAccess {
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
Err(Error::custom("expected unit variant"))
}
fn tuple_variant<V>(
self,
_len: usize,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
Err(Error::custom("expected unit variant"))
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
Err(Error::custom("expected unit variant"))
}
}