use std::marker::PhantomData;
use super::{
node::replace_value,
shared::{Shared, SharedCtxGuard},
value_trait::JsonValueTrait,
};
use crate::{serde::tri, util::reborrow::DormantMutRef, value::node::Value};
#[derive(Debug, Clone, Eq, PartialEq)]
#[repr(transparent)]
pub struct Object(pub(crate) Value);
impl Default for Object {
fn default() -> Self {
Self::new()
}
}
#[doc(hidden)]
pub type Pair = (Value, Value);
pub(crate) const DEFAULT_OBJ_CAP: usize = 4;
impl Object {
#[inline]
pub fn into_value(self) -> Value {
self.0
}
#[inline]
pub const fn new() -> Object {
let value = Value {
meta: super::node::Meta::new(super::node::OBJECT, std::ptr::null()),
data: super::node::Data {
achildren: std::ptr::null_mut(),
},
};
Object(value)
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
let mut v = Self::new();
v.0.reserve::<Pair>(capacity);
v
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
#[inline]
pub fn capacity(&self) -> usize {
self.0.capacity()
}
#[inline]
pub fn get<Q: AsRef<str>>(&self, key: &Q) -> Option<&Value> {
self.0.get_key(key.as_ref())
}
#[inline]
pub fn contains_key<Q: AsRef<str>>(&self, key: &Q) -> bool {
self.get(key).is_some()
}
#[inline]
pub fn get_mut<Q: AsRef<str>>(&mut self, key: &Q) -> Option<&mut Value> {
self.0.get_key_mut(key.as_ref()).map(|v| v.0)
}
#[inline]
pub fn get_key_value<Q: AsRef<str>>(&self, key: &Q) -> Option<(&str, &Value)> {
self.0.get_key_value(key.as_ref())
}
#[inline]
pub fn insert<K: AsRef<str>, V: Into<Value>>(&mut self, key: &K, value: V) -> Option<Value> {
match self.entry(key) {
Entry::Occupied(mut entry) => Some(entry.insert(value)),
Entry::Vacant(entry) => {
entry.insert(value);
None
}
}
}
#[inline]
pub fn remove<Q: AsRef<str>>(&mut self, key: &Q) -> Option<Value> {
self.0.remove_key(key.as_ref())
}
#[inline]
pub fn remove_entry<'k, Q: AsRef<str>>(&mut self, key: &'k Q) -> Option<(&'k str, Value)> {
self.0.remove_key(key.as_ref()).map(|v| (key.as_ref(), v))
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn iter(&self) -> Iter<'_> {
Iter(self.0.iter::<Pair>())
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_> {
IterMut(self.0.iter_mut::<Pair>())
}
#[inline]
pub fn entry<'a, Q: AsRef<str>>(&'a mut self, key: &Q) -> Entry<'a> {
let (obj, mut dormant_obj) = DormantMutRef::new(self);
match obj.0.get_key_mut(key.as_ref()) {
None => {
let obj_re = unsafe { dormant_obj.reborrow() };
if obj_re.0.is_static() {
obj_re.0.mark_shared(Shared::new_ptr());
obj_re.0.mark_root();
}
let shared = obj_re.0.shared();
let key = Value::copy_str(key.as_ref(), shared);
Entry::Vacant(VacantEntry {
key,
dormant_obj,
_marker: PhantomData,
})
}
Some((handle, offset)) => {
Entry::Occupied(OccupiedEntry::new(handle, offset, dormant_obj))
}
}
}
#[inline]
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&str, &mut Value) -> bool,
{
if self.is_empty() {
return;
}
let start: *mut Pair = unsafe { self.0.children_mut_ptr::<Pair>() };
let mut cur = start;
for (k, v) in self.0.iter_mut::<Pair>() {
let key = k.as_str().unwrap();
if f(key, v) {
if !std::ptr::eq(k, cur as *mut Value) {
unsafe { std::ptr::copy_nonoverlapping((k as *mut Value).cast(), cur, 1) };
}
cur = unsafe { cur.add(1) };
} else {
v.take();
}
}
unsafe {
let new_len = cur.offset_from(start) as usize;
self.0.set_len(new_len);
}
}
#[inline]
pub fn append(&mut self, other: &mut Self) {
while let Some((k, v)) = other.0.pop_pair() {
self.0.append_pair((k, v));
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.0.reserve::<Pair>(additional);
}
}
pub struct OccupiedEntry<'a> {
handle: &'a mut Value,
offset: usize,
dormant_obj: DormantMutRef<'a, Object>,
_marker: PhantomData<&'a mut Pair>,
}
impl<'a> OccupiedEntry<'a> {
#[inline]
pub fn get(&self) -> &Value {
self.handle
}
#[inline]
pub fn get_mut(&mut self) -> &mut Value {
self.handle
}
#[inline]
pub fn into_mut(self) -> &'a mut Value {
self.handle
}
#[inline]
pub fn insert<T: Into<Value>>(&mut self, val: T) -> Value {
let obj = unsafe { self.dormant_obj.reborrow() };
let val = {
let _ = SharedCtxGuard::assign(obj.0.shared_parts());
val.into()
};
replace_value(self.handle, val)
}
#[inline]
pub fn remove(mut self) -> Value {
let obj = unsafe { self.dormant_obj.reborrow() };
let (_, val) = obj.0.remove_pair_index(self.offset);
val
}
#[inline]
pub(crate) fn new(
handle: &'a mut Value,
offset: usize,
dormant_obj: DormantMutRef<'a, Object>,
) -> Self {
Self {
handle,
offset,
dormant_obj,
_marker: PhantomData,
}
}
}
pub struct VacantEntry<'a> {
pub(super) key: Value,
pub(super) dormant_obj: DormantMutRef<'a, Object>,
pub(super) _marker: PhantomData<&'a mut Pair>,
}
impl<'a> VacantEntry<'a> {
pub fn insert<T: Into<Value>>(self, val: T) -> &'a mut Value {
let obj = unsafe { self.dormant_obj.awaken() };
obj.reserve(1);
let val = {
let _ = SharedCtxGuard::assign(obj.0.shared_parts());
val.into()
};
let pair = obj.0.append_pair((self.key, val));
&mut pair.1
}
pub fn key(&self) -> &str {
self.key.as_str().unwrap()
}
}
pub enum Entry<'a> {
Vacant(VacantEntry<'a>),
Occupied(OccupiedEntry<'a>),
}
impl<'a> Entry<'a> {
#[inline]
pub fn or_insert<T: Into<Value>>(self, default: T) -> &'a mut Value {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
#[inline]
pub fn or_insert_with<F: FnOnce() -> Value>(self, default: F) -> &'a mut Value {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
#[inline]
pub fn key(&self) -> &str {
match self {
Entry::Occupied(entry) => entry.handle.as_str().unwrap(),
Entry::Vacant(entry) => entry.key(),
}
}
#[inline]
pub fn and_modify<F: FnOnce(&mut Value)>(self, f: F) -> Self {
match self {
Entry::Occupied(entry) => {
f(entry.handle);
Entry::Occupied(entry)
}
Entry::Vacant(entry) => Entry::Vacant(entry),
}
}
#[inline]
pub fn or_default(self) -> &'a mut Value {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(Value::default()),
}
}
#[inline]
pub fn or_insert_with_key<F>(self, default: F) -> &'a mut Value
where
F: FnOnce(&str) -> Value,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(mut entry) => {
let obj = unsafe { entry.dormant_obj.reborrow() };
let value = {
let _ = SharedCtxGuard::assign(obj.0.shared_parts());
default(entry.key())
};
entry.insert(value)
}
}
}
}
use std::{iter::FusedIterator, slice};
macro_rules! impl_entry_iter {
(($name:ident $($generics:tt)*): $item:ty) => {
impl $($generics)* Iterator for $name $($generics)* {
type Item = $item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(k, v)| (k.as_str().unwrap(), v))
}
}
impl $($generics)* DoubleEndedIterator for $name $($generics)* {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|(k, v)| (k.as_str().unwrap(), v))
}
}
impl $($generics)* ExactSizeIterator for $name $($generics)* {
#[inline]
fn len(&self) -> usize {
self.0.len()
}
}
impl $($generics)* FusedIterator for $name $($generics)* {}
};
}
pub struct Iter<'a>(slice::Iter<'a, (Value, Value)>);
impl_entry_iter!((Iter<'a>): (&'a str, &'a Value));
pub struct IterMut<'a>(slice::IterMut<'a, (Value, Value)>);
impl_entry_iter!((IterMut<'a>): (&'a str, &'a mut Value));
pub struct Keys<'a>(Iter<'a>);
impl<'a> Iterator for Keys<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(k, _)| k)
}
}
impl<'a> DoubleEndedIterator for Keys<'a> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|(k, _)| k)
}
}
impl<'a> ExactSizeIterator for Keys<'a> {
#[inline]
fn len(&self) -> usize {
self.0.len()
}
}
impl<'a> FusedIterator for Keys<'a> {}
macro_rules! impl_value_iter {
(($name:ident $($generics:tt)*): $item:ty) => {
impl $($generics)* Iterator for $name $($generics)* {
type Item = $item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(_, v)| v)
}
}
impl $($generics)* DoubleEndedIterator for $name $($generics)* {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|(_, v)| v)
}
}
impl $($generics)* ExactSizeIterator for $name $($generics)* {
#[inline]
fn len(&self) -> usize {
self.0.len()
}
}
impl $($generics)* FusedIterator for $name $($generics)* {}
};
}
pub struct Values<'a>(Iter<'a>);
impl_value_iter!((Values<'a>): &'a Value);
pub struct ValuesMut<'a>(IterMut<'a>);
impl_value_iter!((ValuesMut<'a>): &'a mut Value);
impl<'a> IntoIterator for &'a Object {
type Item = (&'a str, &'a Value);
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut Object {
type Item = (&'a str, &'a mut Value);
type IntoIter = IterMut<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<'a, Q: AsRef<str> + ?Sized> std::ops::Index<&'a Q> for Object {
type Output = Value;
#[inline]
fn index(&self, index: &'a Q) -> &Self::Output {
self.get(&index.as_ref()).unwrap()
}
}
impl<'a, Q: AsRef<str> + ?Sized> std::ops::IndexMut<&'a Q> for Object {
#[inline]
fn index_mut(&mut self, index: &'a Q) -> &mut Self::Output {
self.get_mut(&index.as_ref()).unwrap()
}
}
impl serde::ser::Serialize for Object {
#[inline]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
use serde::ser::SerializeMap;
let mut map = tri!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
tri!(map.serialize_entry(k, v));
}
map.end()
}
}
impl<'de> serde::de::Deserialize<'de> for Object {
#[inline]
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let value: Value =
deserializer.deserialize_newtype_struct(super::de::TOKEN, super::de::ValueVisitor)?;
if value.is_object() {
Ok(Object(value))
} else {
Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Other("not a object"),
&"object",
))
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{from_str, to_string, Array, JsonValueMutTrait};
#[test]
fn test_object_serde() {
let json = r#"{"a": 1, "b": true, "c": null}"#;
let obj: Object = from_str(json).unwrap();
assert_eq!(obj, object! {"a": 1, "b": true, "c": null});
let json = to_string(&obj).unwrap();
assert_eq!(json, r#"{"a":1,"b":true,"c":null}"#);
}
#[test]
fn test_value_object() {
let mut val = crate::from_str::<Value>(r#"{"a": 123, "b": "hello"}"#);
let obj = val.as_object_mut().unwrap();
for i in 0..3 {
let new_node = Value::new_u64(i, std::ptr::null());
obj.insert(&"c", new_node);
assert_eq!(obj["c"], i);
let mut new_node = Array::default();
new_node.push(Value::new_u64(i, std::ptr::null()));
obj.insert(&"d", new_node);
assert_eq!(obj["d"][0], i);
let mut new_node = Array::new_in(obj.0.shared_clone());
new_node.push(Value::new_u64(i, std::ptr::null()));
obj.insert(&"e", new_node);
assert_eq!(obj["e"][0], i);
}
for (i, v) in obj.iter_mut().enumerate() {
*(v.1) = Value::from(&i.to_string());
}
for (i, v) in obj.iter().enumerate() {
assert_eq!(v.1, &Value::from(&i.to_string()));
}
}
}