use crate::collections::{btree_map, BTreeMap};
use crate::{
FromValue, InstallWith, Item, Mut, Named, RawMut, RawRef, RawStr, Ref, ToValue,
UnsafeFromValue, Value, Vm, VmError,
};
use std::borrow;
use std::cmp;
use std::fmt;
use std::hash;
pub type IntoIter = btree_map::IntoIter<String, Value>;
pub type IterMut<'a> = btree_map::IterMut<'a, String, Value>;
pub type Iter<'a> = btree_map::Iter<'a, String, Value>;
pub type Keys<'a> = btree_map::Keys<'a, String, Value>;
pub type Values<'a> = btree_map::Values<'a, String, Value>;
#[derive(Default, Clone)]
#[repr(transparent)]
pub struct Object {
inner: BTreeMap<String, Value>,
}
impl Object {
#[inline]
pub fn new() -> Self {
Self {
inner: BTreeMap::new(),
}
}
#[inline]
pub fn with_capacity(_cap: usize) -> Self {
Self {
inner: BTreeMap::new(),
}
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Value>
where
String: borrow::Borrow<Q>,
Q: hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.get(k)
}
pub fn get_value<Q: ?Sized, T>(&self, k: &Q) -> Result<Option<T>, VmError>
where
String: borrow::Borrow<Q>,
Q: hash::Hash + cmp::Eq + cmp::Ord,
T: FromValue,
{
let value = match self.inner.get(k) {
Some(value) => value.clone(),
None => return Ok(None),
};
Ok(Some(T::from_value(value)?))
}
#[inline]
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut Value>
where
String: borrow::Borrow<Q>,
Q: hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.get_mut(k)
}
#[inline]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
String: borrow::Borrow<Q>,
Q: hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.contains_key(k)
}
#[inline]
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Value>
where
String: borrow::Borrow<Q>,
Q: hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.remove(k)
}
#[inline]
pub fn insert_value<T>(&mut self, k: String, v: T) -> Result<(), VmError>
where
T: ToValue,
{
self.inner.insert(k, v.to_value()?);
Ok(())
}
#[inline]
pub fn insert(&mut self, k: String, v: Value) -> Option<Value> {
self.inner.insert(k, v)
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear();
}
pub fn into_inner(self) -> BTreeMap<String, Value> {
self.inner
}
pub fn iter(&self) -> Iter<'_> {
self.inner.iter()
}
pub fn keys(&self) -> Keys<'_> {
self.inner.keys()
}
pub fn values(&self) -> Values<'_> {
self.inner.values()
}
pub fn iter_mut(&mut self) -> IterMut<'_> {
self.inner.iter_mut()
}
pub(crate) fn value_ptr_eq(vm: &mut Vm, a: &Self, b: &Self) -> Result<bool, VmError> {
map_ptr_eq(vm, &a.inner, &b.inner)
}
pub(crate) fn debug_struct<'a>(&'a self, item: &'a Item) -> DebugStruct<'a> {
DebugStruct { item, st: self }
}
pub fn into_iterator(&self) -> crate::Iterator {
crate::Iterator::from("std::object::Iter", self.clone().into_iter())
}
}
impl<'a> IntoIterator for &'a Object {
type Item = (&'a String, &'a Value);
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut Object {
type Item = (&'a String, &'a mut Value);
type IntoIter = IterMut<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl IntoIterator for Object {
type Item = (String, Value);
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl fmt::Debug for Object {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.inner.iter()).finish()
}
}
impl std::iter::FromIterator<(String, Value)> for Object {
fn from_iter<T: IntoIterator<Item = (String, Value)>>(src: T) -> Self {
Self {
inner: src.into_iter().collect(),
}
}
}
impl FromValue for Object {
fn from_value(value: Value) -> Result<Self, VmError> {
Ok(value.into_object()?.take()?)
}
}
impl FromValue for Mut<Object> {
fn from_value(value: Value) -> Result<Self, VmError> {
let object = value.into_object()?;
let object = object.into_mut()?;
Ok(object)
}
}
impl FromValue for Ref<Object> {
fn from_value(value: Value) -> Result<Self, VmError> {
let object = value.into_object()?;
let object = object.into_ref()?;
Ok(object)
}
}
impl UnsafeFromValue for &Object {
type Output = *const Object;
type Guard = RawRef;
fn from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
let object = value.into_object()?;
let object = object.into_ref()?;
Ok(Ref::into_raw(object))
}
unsafe fn unsafe_coerce(output: Self::Output) -> Self {
&*output
}
}
impl UnsafeFromValue for &mut Object {
type Output = *mut Object;
type Guard = RawMut;
fn from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
let object = value.into_object()?;
let object = object.into_mut()?;
Ok(Mut::into_raw(object))
}
unsafe fn unsafe_coerce(output: Self::Output) -> Self {
&mut *output
}
}
impl Named for Object {
const NAME: RawStr = RawStr::from_str("Object");
}
impl InstallWith for Object {}
pub struct DebugStruct<'a> {
item: &'a Item,
st: &'a Object,
}
impl fmt::Display for DebugStruct<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct(&self.item.to_string());
for (key, value) in self.st.iter() {
d.field(key, value);
}
d.finish()
}
}
pub(crate) fn map_ptr_eq<K>(
vm: &mut Vm,
a: &BTreeMap<K, Value>,
b: &BTreeMap<K, Value>,
) -> Result<bool, VmError>
where
K: cmp::Eq + cmp::Ord,
K: hash::Hash,
{
if a.len() != b.len() {
return Ok(false);
}
for (key, a) in a.iter() {
let b = match b.get(key) {
Some(b) => b,
None => return Ok(false),
};
if !Value::value_ptr_eq(vm, a, b)? {
return Ok(false);
}
}
Ok(true)
}