use core::borrow;
use core::cmp;
use core::fmt;
use core::hash;
use core::iter;
use crate as rune;
use crate::alloc::hash_map;
use crate::alloc::hashbrown::raw::RawIter;
use crate::alloc::prelude::*;
use crate::alloc::{self, String};
use crate::runtime::{
FieldMap, FromValue, ProtocolCaller, RawAnyGuard, Ref, ToValue, Value, VmError, VmResult,
};
use crate::Any;
pub type IntoIter = hash_map::IntoIter<String, Value>;
pub type IterMut<'a> = hash_map::IterMut<'a, String, Value>;
pub type Iter<'a> = hash_map::Iter<'a, String, Value>;
pub type Keys<'a> = hash_map::Keys<'a, String, Value>;
pub type Values<'a> = hash_map::Values<'a, String, Value>;
#[derive(Any, Default)]
#[repr(transparent)]
#[rune(item = ::std::object)]
pub struct Object {
inner: FieldMap<String, Value>,
}
impl Object {
#[inline]
#[rune::function(keep, path = Self::new)]
pub fn new() -> Self {
Self {
inner: crate::runtime::new_field_map(),
}
}
#[inline]
#[rune::function(path = Self::with_capacity)]
pub(crate) fn rune_with_capacity(capacity: usize) -> VmResult<Self> {
VmResult::Ok(vm_try!(Self::with_capacity(capacity)))
}
pub fn with_capacity(capacity: usize) -> alloc::Result<Self> {
Ok(Self {
inner: crate::runtime::new_field_hash_map_with_capacity(capacity)?,
})
}
#[inline]
#[rune::function(keep)]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
#[rune::function(keep)]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn get<Q>(&self, k: &Q) -> Option<&Value>
where
String: borrow::Borrow<Q>,
Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.get(k)
}
pub fn get_value<Q, T>(&self, k: &Q) -> VmResult<Option<T>>
where
String: borrow::Borrow<Q>,
Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
T: FromValue,
{
let value = match self.inner.get(k) {
Some(value) => value.clone(),
None => return VmResult::Ok(None),
};
VmResult::Ok(Some(vm_try!(T::from_value(value))))
}
#[inline]
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut Value>
where
String: borrow::Borrow<Q>,
Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.get_mut(k)
}
#[inline]
pub fn contains_key<Q>(&self, k: &Q) -> bool
where
String: borrow::Borrow<Q>,
Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.contains_key(k)
}
#[inline]
pub fn remove<Q>(&mut self, k: &Q) -> Option<Value>
where
String: borrow::Borrow<Q>,
Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
{
self.inner.remove(k)
}
#[inline]
pub fn insert_value<T>(&mut self, k: String, v: T) -> VmResult<()>
where
T: ToValue,
{
vm_try!(self.inner.try_insert(k, vm_try!(v.to_value())));
VmResult::Ok(())
}
#[inline]
#[rune::function(path = Self::insert)]
pub(crate) fn rune_insert(&mut self, k: String, v: Value) -> VmResult<Option<Value>> {
VmResult::Ok(vm_try!(self.inner.try_insert(k, v)))
}
#[inline]
pub fn insert(&mut self, k: String, v: Value) -> alloc::Result<Option<Value>> {
self.inner.try_insert(k, v)
}
#[inline]
#[rune::function(keep)]
pub fn clear(&mut self) {
self.inner.clear();
}
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()
}
#[rune::function(keep, path = Self::iter)]
pub fn rune_iter(this: Ref<Self>) -> RuneIter {
let iter = unsafe { this.inner.raw_table().iter() };
let (_, guard) = Ref::into_raw(this);
RuneIter { iter, guard }
}
#[rune::function(keep, path = Self::keys)]
pub fn rune_keys(this: Ref<Self>) -> RuneIterKeys {
let iter = unsafe { this.inner.raw_table().iter() };
let (_, guard) = Ref::into_raw(this);
RuneIterKeys { iter, guard }
}
#[rune::function(keep, path = Self::values)]
pub fn rune_values(this: Ref<Self>) -> RuneValues {
let iter = unsafe { this.inner.raw_table().iter() };
let (_, guard) = Ref::into_raw(this);
RuneValues { iter, guard }
}
pub(crate) fn partial_eq_with(
a: &Self,
b: &Self,
caller: &mut dyn ProtocolCaller,
) -> VmResult<bool> {
if a.len() != b.len() {
return VmResult::Ok(false);
}
for (k1, v1) in a.iter() {
let Some(v2) = b.get(k1) else {
return VmResult::Ok(false);
};
if !vm_try!(Value::partial_eq_with(v1, v2, caller)) {
return VmResult::Ok(false);
}
}
VmResult::Ok(true)
}
pub(crate) fn eq_with(
a: &Self,
b: &Self,
eq: fn(&Value, &Value, &mut dyn ProtocolCaller) -> VmResult<bool>,
caller: &mut dyn ProtocolCaller,
) -> VmResult<bool> {
if a.inner.len() != b.inner.len() {
return VmResult::Ok(false);
}
for (key, a) in a.inner.iter() {
let Some(b) = b.inner.get(key) else {
return VmResult::Ok(false);
};
if !vm_try!(eq(a, b, caller)) {
return VmResult::Ok(false);
}
}
VmResult::Ok(true)
}
}
impl TryClone for Object {
fn try_clone(&self) -> alloc::Result<Self> {
Ok(Self {
inner: self.inner.try_clone()?,
})
}
}
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 {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.inner.iter()).finish()
}
}
#[derive(Any)]
#[rune(item = ::std::object, name = Iter)]
pub struct RuneIter {
iter: RawIter<(String, Value)>,
#[allow(unused)]
guard: RawAnyGuard,
}
impl RuneIter {
#[rune::function(instance, keep, protocol = NEXT)]
pub fn next(&mut self) -> VmResult<Option<(String, Value)>> {
unsafe {
let Some(bucket) = self.iter.next() else {
return VmResult::Ok(None);
};
let (key, value) = bucket.as_ref();
let key = vm_try!(key.try_clone());
VmResult::Ok(Some((key, value.clone())))
}
}
#[rune::function(instance, keep, protocol = SIZE_HINT)]
pub fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[rune::function(instance, keep, protocol = LEN)]
pub fn len(&self) -> usize {
self.iter.len()
}
}
impl iter::Iterator for RuneIter {
type Item = Result<(String, Value), VmError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match RuneIter::next(self) {
VmResult::Ok(Some(value)) => Some(Ok(value)),
VmResult::Ok(None) => None,
VmResult::Err(err) => Some(Err(err)),
}
}
}
#[derive(Any)]
#[rune(item = ::std::object, name = Keys)]
pub struct RuneIterKeys {
iter: RawIter<(String, Value)>,
#[allow(unused)]
guard: RawAnyGuard,
}
impl RuneIterKeys {
#[rune::function(instance, keep, protocol = NEXT)]
pub fn next(&mut self) -> VmResult<Option<String>> {
unsafe {
let Some(bucket) = self.iter.next() else {
return VmResult::Ok(None);
};
let (key, _) = bucket.as_ref();
let key = vm_try!(key.try_clone());
VmResult::Ok(Some(key))
}
}
#[rune::function(instance, keep, protocol = SIZE_HINT)]
pub fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[rune::function(instance, keep, protocol = LEN)]
pub fn len(&self) -> usize {
self.iter.len()
}
}
impl iter::Iterator for RuneIterKeys {
type Item = Result<String, VmError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match RuneIterKeys::next(self) {
VmResult::Ok(Some(value)) => Some(Ok(value)),
VmResult::Ok(None) => None,
VmResult::Err(err) => Some(Err(err)),
}
}
}
#[derive(Any)]
#[rune(item = ::std::object, name = Values)]
pub struct RuneValues {
iter: RawIter<(String, Value)>,
#[allow(unused)]
guard: RawAnyGuard,
}
impl RuneValues {
#[rune::function(instance, keep, protocol = NEXT)]
pub fn next(&mut self) -> VmResult<Option<Value>> {
unsafe {
let Some(bucket) = self.iter.next() else {
return VmResult::Ok(None);
};
let (_, value) = bucket.as_ref();
VmResult::Ok(Some(value.clone()))
}
}
#[rune::function(instance, keep, protocol = SIZE_HINT)]
pub fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[rune::function(instance, keep, protocol = LEN)]
pub fn len(&self) -> usize {
self.iter.len()
}
}
impl iter::Iterator for RuneValues {
type Item = Result<Value, VmError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match RuneValues::next(self) {
VmResult::Ok(Some(value)) => Some(Ok(value)),
VmResult::Ok(None) => None,
VmResult::Err(err) => Some(Err(err)),
}
}
}