use form_urlencoded::{parse, Parse as UrlEncodedParse};
use indexmap::map::{self, IndexMap};
use serde_core::{
de::{self, value::MapDeserializer, Deserialize},
forward_to_deserialize_any,
};
#[doc(inline)]
pub use serde_core::de::value::Error;
pub mod empty_as_none;
mod part;
mod utils;
mod val_or_vec;
use self::{empty_as_none::EmptyAsNone, part::Part, val_or_vec::ValOrVec};
pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result<T, Error>
where
T: Deserialize<'de>,
{
T::deserialize(Deserializer::from_bytes(input))
}
pub fn from_str<'de, T>(input: &'de str) -> Result<T, Error>
where
T: Deserialize<'de>,
{
from_bytes(input.as_bytes())
}
pub struct Deserializer<'de> {
inner: UrlEncodedParse<'de>,
}
impl<'de> Deserializer<'de> {
pub fn new(parse: UrlEncodedParse<'de>) -> Self {
Deserializer { inner: parse }
}
pub fn from_bytes(input: &'de [u8]) -> Self {
Self::new(parse(input))
}
}
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(MapDeserializer::new(group_entries(self.inner).into_iter()))
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_seq(MapDeserializer::new(PartIterator(self.inner)))
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
let deserializer = MapDeserializer::new(PartIterator(self.inner));
deserializer.end()?;
visitor.visit_unit()
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
forward_to_deserialize_any! {
bool
u8
u16
u32
u64
i8
i16
i32
i64
f32
f64
char
str
string
option
bytes
byte_buf
unit_struct
tuple_struct
struct
identifier
tuple
enum
ignored_any
}
}
pub fn empty_as_none<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
T: Deserialize<'de>,
D: de::Deserializer<'de>,
{
EmptyAsNone::deserialize(deserializer).map(|EmptyAsNone(option)| option)
}
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)))
}
}
#[cfg(feature = "std")]
type RandomState = std::collections::hash_map::RandomState;
#[cfg(not(feature = "std"))]
type RandomState = compile_error!("the `std` feature is currently required");
fn group_entries(
parse: UrlEncodedParse<'_>,
) -> IndexMap<Part<'_>, ValOrVec<Part<'_>>, RandomState> {
use map::Entry::*;
let mut res = IndexMap::default();
#[cfg(feature = "std")]
for (key, value) in parse {
match res.entry(Part(key)) {
Vacant(v) => {
v.insert(ValOrVec::Val(Part(value)));
}
Occupied(mut o) => {
o.get_mut().push(Part(value));
}
}
}
res
}
#[cfg(test)]
mod tests;