#[allow(unused_imports)]
use crate::{
AccessKind, AnyRef, ApplyError, FieldPathQueryMut, MapAccessMut, MapEntryVisitor, MutationBatch,
Object, ObjectMut, ObjectOps, ObjectRef, ObjectRefMut, PatchOperation, PathSegment, Reflect,
ReflectMut, ReflectiveError, SequenceAccess, SequenceAccessMut, StructAccess, TupleAccess,
TypeInfo, ValueKind, VariantFields, VariantFieldsMut, apply_patch,
};
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::string::String;
use core::any::{Any, TypeId};
#[cfg(feature = "std")]
use core::hash::Hash;
#[cfg(feature = "std")]
use std::collections::HashMap;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MoveItemError {
Unsupported,
IndexOutOfBounds,
RemoveFailed,
InsertFailed,
RestoreFailed,
}
pub(crate) fn as_map_key<K: 'static>(candidate: &K) -> Option<String> {
let any = candidate as &dyn Any;
if let Some(value) = any.downcast_ref::<String>() {
Some(value.clone())
} else {
any
.downcast_ref::<&'static str>()
.map(|value| (*value).to_owned())
}
}
fn string_map_key<'a>(key: AnyRef<'a>) -> Option<&'a str> {
key
.to_ref::<String>()
.map(String::as_str)
.or_else(|| key.to_ref::<&'static str>().copied())
}
macro_rules! map_key_lookup {
($get:ident, $get_mut:ident, $map:ident $(, $extra:ident : $extra_bound:path)* ; $($key_bound:path),+) => {
pub(crate) fn $get<'a, K, V, $($extra),*>(map: &'a $map<K, V, $($extra),*>, key: &str) -> Option<&'a V>
where
K: $($key_bound +)+ 'static,
V: 'static,
$($extra: $extra_bound + 'static,)*
{
if let Some(map) = (map as &dyn Any).downcast_ref::<$map<String, V, $($extra),*>>() {
return map.get(key);
}
if let Some(map) = (map as &dyn Any).downcast_ref::<$map<&'static str, V, $($extra),*>>() {
return map.get(key);
}
None
}
pub(crate) fn $get_mut<'a, K, V, $($extra),*>(map: &'a mut $map<K, V, $($extra),*>, key: &str) -> Option<&'a mut V>
where
K: $($key_bound +)+ 'static,
V: 'static,
$($extra: $extra_bound + 'static,)*
{
if TypeId::of::<K>() == TypeId::of::<String>() {
let map = (map as &mut dyn Any)
.downcast_mut::<$map<String, V, $($extra),*>>()
.unwrap();
return map.get_mut(key);
}
if TypeId::of::<K>() == TypeId::of::<&'static str>() {
let map = (map as &mut dyn Any)
.downcast_mut::<$map<&'static str, V, $($extra),*>>()
.unwrap();
return map.get_mut(key);
}
None
}
};
}
map_key_lookup!(btree_map_get, btree_map_get_mut, BTreeMap; Ord);
#[cfg(feature = "std")]
map_key_lookup!(hash_map_get, hash_map_get_mut, HashMap, S: core::hash::BuildHasher; Eq, Hash);
pub trait TypedMapAccess<K> {
fn key_typed(&self, key: &K) -> Option<ObjectRef<'_>>;
}
pub trait TypedMapAccessMut<K> {
fn key_typed_mut(&mut self, key: &K) -> Option<ObjectRefMut<'_>>;
}
#[inline]
fn items_eq<A, B>(a: &A, b: &B) -> bool
where
A: SequenceAccess + ?Sized,
B: SequenceAccess + ?Sized,
{
a.len() == b.len()
&& (0..a.len()).all(|index| match (a.item(index), b.item(index)) {
(Some(x), Some(y)) => x == y,
_ => false,
})
}
#[inline]
fn named_fields_eq<A, B>(a: &A, b: &B) -> bool
where
A: StructAccess + ?Sized,
B: StructAccess + ?Sized,
{
let names = a.field_names();
if names != b.field_names() {
return false;
}
for &name in names {
match (a.field(name), b.field(name)) {
(Some(x), Some(y)) if x == y => {}
_ => return false,
}
}
true
}
#[inline]
fn positional_fields_eq<A, B>(a: &A, b: &B) -> bool
where
A: TupleAccess + ?Sized,
B: TupleAccess + ?Sized,
{
let len = a.len();
if len != b.len() {
return false;
}
for index in 0..len {
match (a.item(index), b.item(index)) {
(Some(x), Some(y)) if x == y => {}
_ => return false,
}
}
true
}
#[inline]
fn structural_eq<T: Meta + ?Sized>(this: &T, other: &dyn Meta) -> bool {
match (this.reflect(), other.reflect()) {
(Reflect::Option(a), Reflect::Option(b)) => match (a, b) {
(Some(a), Some(b)) => a == b,
(None, None) => true,
_ => false,
},
(Reflect::Struct(a), Reflect::Struct(b)) => named_fields_eq(a, b),
(Reflect::Tuple(a), Reflect::Tuple(b)) => positional_fields_eq(a, b),
(Reflect::Enum(a), Reflect::Enum(b)) => {
a.variant_name() == b.variant_name()
&& match (a.fields(), b.fields()) {
(VariantFields::Unit, VariantFields::Unit) => true,
(VariantFields::Named(a), VariantFields::Named(b)) => named_fields_eq(a, b),
(VariantFields::Positional(a), VariantFields::Positional(b)) => {
positional_fields_eq(a, b)
}
_ => false,
}
}
(Reflect::Map(a), Reflect::Map(b)) => {
if a.len() != b.len() {
return false;
}
let mut equal = true;
a.visit_entries(&mut |key, value| {
let Some(key) = string_map_key(key) else {
equal = false;
return false;
};
equal = b.key(key).is_some_and(|other_value| value == other_value);
equal
});
equal
}
(Reflect::Sequence(a), Reflect::Sequence(b)) => items_eq(a, b),
(Reflect::KeyedSequence(a), Reflect::KeyedSequence(b)) => items_eq(a, b),
_ => false,
}
}
pub trait Meta: Any {
fn type_info(&self) -> TypeInfo {
TypeInfo::of::<Self>()
}
fn reflect(&self) -> Reflect<'_>;
fn field_dyn(&self, name: &str) -> Option<ObjectRef<'_>> {
match self.reflect() {
Reflect::Struct(value) => value.field(name),
Reflect::Enum(value) => match value.fields() {
VariantFields::Named(fields) => fields.field(name),
_ => None,
},
Reflect::Option(value) => value?.field(name),
_ => None,
}
}
fn kind_dyn(&self) -> ValueKind {
self.reflect().kind()
}
fn len_dyn(&self) -> Option<usize> {
match self.reflect() {
Reflect::Tuple(value) => Some(value.len()),
Reflect::Enum(value) => match value.fields() {
VariantFields::Positional(fields) => Some(fields.len()),
_ => None,
},
Reflect::Sequence(value) => Some(value.len()),
Reflect::KeyedSequence(value) => Some(value.len()),
Reflect::Map(value) => Some(value.len()),
Reflect::Option(value) => Some(usize::from(value.is_some())),
Reflect::Struct(_) | Reflect::Scalar => None,
}
}
fn field_names_dyn(&self) -> &'static [&'static str] {
match self.reflect() {
Reflect::Struct(value) => value.field_names(),
Reflect::Enum(value) => match value.fields() {
VariantFields::Named(fields) => fields.field_names(),
_ => &[],
},
Reflect::Option(Some(value)) => value.field_names(),
_ => &[],
}
}
fn visit_map_entries_dyn(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
match self.reflect() {
Reflect::Map(value) => {
value.visit_entries(visitor);
true
}
Reflect::Option(Some(value)) => value.visit_map_entries(visitor),
_ => false,
}
}
fn access_kind_dyn(&self) -> Option<AccessKind> {
match self.reflect() {
Reflect::Scalar => None,
Reflect::Struct(_) => Some(AccessKind::Field),
Reflect::Tuple(_) | Reflect::Sequence(_) => Some(AccessKind::Index),
Reflect::Enum(value) => Some(match value.fields() {
VariantFields::Positional(_) => AccessKind::Index,
VariantFields::Unit | VariantFields::Named(_) => AccessKind::Field,
}),
Reflect::KeyedSequence(_) => Some(AccessKind::KeyedItem),
Reflect::Map(_) => Some(AccessKind::Key),
Reflect::Option(value) => value?.access_kind(),
}
}
fn is_variant_dyn(&self, name: &str) -> Option<bool> {
match self.reflect() {
Reflect::Enum(value) => Some(value.variant_name() == name),
_ => None,
}
}
fn item_dyn(&self, index: usize) -> Option<ObjectRef<'_>> {
match self.reflect() {
Reflect::Tuple(value) => value.item(index),
Reflect::Enum(value) => match value.fields() {
VariantFields::Positional(fields) => fields.item(index),
_ => None,
},
Reflect::Sequence(value) => value.item(index),
Reflect::KeyedSequence(value) => value.item(index),
Reflect::Option(value) => value.filter(|_| index == 0),
Reflect::Struct(_) | Reflect::Map(_) | Reflect::Scalar => None,
}
}
fn key_dyn(&self, key: &str) -> Option<ObjectRef<'_>> {
match self.reflect() {
Reflect::Map(value) => value.key(key),
Reflect::KeyedSequence(value) => value.key(key),
Reflect::Option(value) => value?.key(key),
_ => None,
}
}
fn eq_dyn(&self, other: &dyn Meta) -> bool {
self.type_info() == other.type_info() && structural_eq(self, other)
}
fn into_any(self: Box<Self>) -> Box<dyn Any>;
fn as_any(&self) -> &dyn Any;
}
pub trait MetaMut: Meta {
fn reflect_mut(&mut self) -> ReflectMut<'_>;
fn field_mut_dyn(&mut self, name: &str) -> Option<ObjectRefMut<'_>> {
match self.reflect_mut() {
ReflectMut::Struct(value) => value.field_mut(name),
ReflectMut::Enum(value) => match value.fields_mut() {
VariantFieldsMut::Named(fields) => fields.field_mut(name),
_ => None,
},
ReflectMut::Option(value) => value.value_mut()?.inner.field_mut_dyn(name),
_ => None,
}
}
fn item_mut_dyn(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
match self.reflect_mut() {
ReflectMut::Tuple(value) => value.item_mut(index),
ReflectMut::Enum(value) => match value.fields_mut() {
VariantFieldsMut::Positional(fields) => fields.item_mut(index),
_ => None,
},
ReflectMut::Sequence(value) => value.item_mut(index),
ReflectMut::KeyedSequence(value) => value.item_mut(index),
ReflectMut::Option(value) if index == 0 => value.value_mut(),
_ => None,
}
}
fn key_mut_dyn(&mut self, key: &str) -> Option<ObjectRefMut<'_>> {
match self.reflect_mut() {
ReflectMut::Map(value) => value.key_mut(key),
ReflectMut::KeyedSequence(value) => value.key_mut(key),
ReflectMut::Option(value) => value.value_mut()?.inner.key_mut_dyn(key),
_ => None,
}
}
fn insert_key_dyn(&mut self, key: &str, value: Object) -> Result<ObjectRefMut<'_>, Object> {
match self.reflect_mut() {
ReflectMut::Map(map) => map.insert_key(key, value),
ReflectMut::Option(option) => match option.value_mut() {
Some(inner) => inner.inner.insert_key_dyn(key, value),
None => Err(value),
},
_ => Err(value),
}
}
fn insert_item_dyn(&mut self, index: usize, value: Object) -> Result<ObjectRefMut<'_>, Object> {
match self.reflect_mut() {
ReflectMut::Sequence(sequence) => sequence.insert_item(index, value),
ReflectMut::KeyedSequence(sequence) => sequence.insert_item(index, value),
ReflectMut::Option(option) if index == 0 => option.insert_value(value),
_ => Err(value),
}
}
fn push_item_dyn(&mut self, value: Object) -> Result<ObjectRefMut<'_>, Object> {
match self.reflect_mut() {
ReflectMut::Sequence(sequence) => sequence.push_item(value),
ReflectMut::KeyedSequence(sequence) => sequence.push_item(value),
_ => Err(value),
}
}
fn remove_key_dyn(&mut self, key: &str) -> Option<Object> {
match self.reflect_mut() {
ReflectMut::Map(value) => value.remove_key(key),
ReflectMut::Option(value) => value.value_mut()?.inner.remove_key_dyn(key),
_ => None,
}
}
fn remove_item_dyn(&mut self, index: usize) -> Option<Object> {
match self.reflect_mut() {
ReflectMut::Sequence(value) => value.remove_item(index),
ReflectMut::KeyedSequence(value) => value.remove_item(index),
ReflectMut::Option(value) if index == 0 => value.take_value(),
_ => None,
}
}
fn move_item_dyn(&mut self, from: usize, to: usize) -> Result<(), MoveItemError> {
match self.reflect_mut() {
ReflectMut::Sequence(value) => value.move_item(from, to),
ReflectMut::KeyedSequence(value) => value.move_item(from, to),
_ => Err(MoveItemError::Unsupported),
}
}
fn set_dyn(&mut self, value: Object) -> Result<(), Object>;
fn replace_dyn(&mut self, value: Object) -> Result<Object, Object>;
#[doc(hidden)]
fn as_meta(&self) -> &dyn Meta;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
macro_rules! set_body {
() => {
fn replace_dyn(&mut self, value: Object) -> Result<Object, Object> {
if !value.is::<Self>() {
return Err(value);
}
let replacement = *value.into_inner().into_any().downcast::<Self>().unwrap();
Ok(Object::new(core::mem::replace(self, replacement)))
}
fn set_dyn(&mut self, value: Object) -> Result<(), Object> {
if !value.is::<Self>() {
return Err(value);
}
*self = *value.into_inner().into_any().downcast::<Self>().unwrap();
Ok(())
}
fn as_meta(&self) -> &dyn Meta {
self
}
};
}