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::*;
#[cfg(feature = "known-key")]
pub type ObjectHasher = crate::known_key::NotSoRandomState;
#[cfg(not(feature = "known-key"))]
pub type ObjectHasher = halfbrown::DefaultHashBuilder;
pub fn deserialize<'de, Value, Key>(s: &'de mut [u8]) -> Result<Value>
where
Value: Builder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + '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, ObjectHasher>> + '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, ObjectHasher>>
+ 'de,
Key: Hash + Eq + From<&'de str>,
{
pub fn from_deserializer(de: Deserializer<'de>) -> Self {
Self {
de,
_marker: PhantomData,
}
}
#[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, count: _ } => self.parse_array(len),
Node::Object { len, count: _ } => 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, ObjectHasher> =
HashMap::with_capacity_and_hasher(len, ObjectHasher::default());
for _ in 0..len {
if let Node::String(key) = unsafe { self.de.next_() } {
#[cfg(not(feature = "value-no-dup-keys"))]
res.insert_nocheck(key.into(), self.parse());
#[cfg(feature = "value-no-dup-keys")]
res.insert(key.into(), self.parse());
} else {
unreachable!();
}
}
Value::from(res)
}
}