mod cursor;
mod freeze;
mod iter;
mod mutate;
mod serde;
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use core::cmp::Ordering;
use core::fmt;
use crate::value::Value;
#[cfg(feature = "rvm")]
pub use cursor::ObjectCursor;
pub use iter::{IntoIter, Iter, IterMut};
#[derive(Default, Clone)]
pub struct Object {
pub(super) repr: Repr,
}
#[derive(Clone)]
pub(super) enum Repr {
Empty,
Frozen(Box<[(Value, Value)]>),
BTree(BTreeMap<Value, Value>),
}
impl Default for Repr {
#[inline]
fn default() -> Self {
Repr::Empty
}
}
impl Object {
#[inline]
pub const fn new() -> Self {
Self { repr: Repr::Empty }
}
#[inline]
pub fn len(&self) -> usize {
match &self.repr {
Repr::Empty => 0,
Repr::Frozen(v) => v.len(),
Repr::BTree(m) => m.len(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, key: &Value) -> Option<&Value> {
match &self.repr {
Repr::Empty => None,
Repr::Frozen(v) => match v.binary_search_by(|(k, _)| k.cmp(key)) {
Ok(i) => Some(&v[i].1),
Err(_) => None,
},
Repr::BTree(m) => m.get(key),
}
}
#[inline]
pub fn contains_key(&self, key: &Value) -> bool {
self.get(key).is_some()
}
pub fn get_mut(&mut self, key: &Value) -> Option<&mut Value> {
match &mut self.repr {
Repr::Empty => None,
Repr::Frozen(v) => match v.binary_search_by(|(k, _)| k.cmp(key)) {
Ok(i) => Some(&mut v[i].1),
Err(_) => None,
},
Repr::BTree(m) => m.get_mut(key),
}
}
pub fn iter(&self) -> impl Iterator<Item = (&Value, &Value)> + '_ {
self.iter_sorted()
}
#[inline]
pub fn iter_sorted(&self) -> Iter<'_> {
Iter {
inner: match &self.repr {
Repr::Empty => iter::IterInner::Empty,
Repr::Frozen(v) => iter::IterInner::Frozen(v.iter()),
Repr::BTree(m) => iter::IterInner::BTree(m.iter()),
},
}
}
pub fn keys(&self) -> impl Iterator<Item = &Value> + '_ {
self.iter_sorted().map(|(k, _)| k)
}
pub fn keys_sorted(&self) -> impl Iterator<Item = &Value> + '_ {
self.iter_sorted().map(|(k, _)| k)
}
pub fn values(&self) -> impl Iterator<Item = &Value> + '_ {
self.iter_sorted().map(|(_, v)| v)
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_> {
self.thaw();
IterMut {
inner: match &mut self.repr {
Repr::Empty | Repr::Frozen(_) => iter::IterMutInner::Empty,
Repr::BTree(m) => iter::IterMutInner::BTree(m.iter_mut()),
},
}
}
}
impl PartialEq for Object {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
self.iter_sorted().eq(other.iter_sorted())
}
}
impl Eq for Object {}
impl Ord for Object {
fn cmp(&self, other: &Self) -> Ordering {
self.iter_sorted().cmp(other.iter_sorted())
}
}
impl PartialOrd for Object {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl fmt::Debug for Object {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter_sorted()).finish()
}
}
impl Extend<(Value, Value)> for Object {
fn extend<I: IntoIterator<Item = (Value, Value)>>(&mut self, iter: I) {
for (k, v) in iter {
self.insert(k, v);
}
}
}
impl FromIterator<(Value, Value)> for Object {
fn from_iter<I: IntoIterator<Item = (Value, Value)>>(iter: I) -> Self {
let mut o = Object::new();
for (k, v) in iter {
o.insert(k, v);
}
o
}
}
impl From<BTreeMap<Value, Value>> for Object {
fn from(map: BTreeMap<Value, Value>) -> Self {
if map.is_empty() {
Self { repr: Repr::Empty }
} else {
Self {
repr: Repr::BTree(map),
}
}
}
}
impl From<Object> for Value {
#[inline]
fn from(o: Object) -> Self {
o.into_value()
}
}