pub mod borrowed;
pub mod owned;
pub mod tape;
pub use self::borrowed::{
to_value as to_borrowed_value, to_value_with_buffers as to_borrowed_value_with_buffers,
Value as BorrowedValue,
};
pub use self::owned::{
to_value as to_owned_value, to_value_with_buffers as to_owned_value_with_buffers,
Value as OwnedValue,
};
use crate::safer_unchecked::GetSaferUnchecked;
use crate::{Deserializer, Result};
use halfbrown::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use tape::Node;
pub use value_trait::*;
pub fn deserialize<'de, Value, Key>(s: &'de mut [u8]) -> Result<Value>
where
Value: Builder<'de> + From<Vec<Value>> + From<HashMap<Key, Value>> + 'de,
Key: Hash + Eq + From<&'de str>,
{
match Deserializer::from_slice(s) {
Ok(de) => Ok(ValueDeserializer::from_deserializer(de).parse()),
Err(e) => Err(e),
}
}
struct ValueDeserializer<'de, Value, Key>
where
Value: Builder<'de> + From<Vec<Value>> + From<HashMap<Key, Value>> + 'de,
Key: Hash + Eq + From<&'de str>,
{
de: Deserializer<'de>,
_marker: PhantomData<(Value, Key)>,
}
impl<'de, Value, Key> ValueDeserializer<'de, Value, Key>
where
Value: Builder<'de> + From<&'de str> + From<Vec<Value>> + From<HashMap<Key, Value>> + 'de,
Key: Hash + Eq + From<&'de str>,
{
pub fn from_deserializer(de: Deserializer<'de>) -> Self {
Self {
de,
_marker: PhantomData::default(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
pub fn parse(&mut self) -> Value {
match unsafe { self.de.next_() } {
Node::Static(s) => Value::from(s),
Node::String(s) => Value::from(s),
Node::Array(len, _) => self.parse_array(len),
Node::Object(len, _) => self.parse_map(len),
}
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
#[allow(clippy::uninit_vec)]
fn parse_array(&mut self, len: usize) -> Value {
let mut res = Vec::with_capacity(len);
unsafe {
res.set_len(len);
for i in 0..len {
std::ptr::write(res.get_kinda_unchecked_mut(i), self.parse());
}
}
Value::from(res)
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
fn parse_map(&mut self, len: usize) -> Value {
let mut res: HashMap<Key, Value> = HashMap::with_capacity(len);
for _ in 0..len {
if let Node::String(key) = unsafe { self.de.next_() } {
res.insert_nocheck(key.into(), self.parse());
} else {
unreachable!();
}
}
Value::from(res)
}
}