#[allow(unused_imports)]
use crate::{
AccessKind, ApplyError, FieldPathQuery, FieldPathQueryMut, MapEntryVisitor, Meta, MetaMut,
MutationBatch, PatchOperation, PathSegment, ReflectiveError, TypeInfo, TypedPath, ValueKind,
apply_patch,
};
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::vec::Vec;
use core::any::Any;
use core::fmt;
use core::ops::{Deref, DerefMut};
fn fmt_meta<T: Meta + ?Sized>(f: &mut fmt::Formatter<'_>, name: &str, meta: &T) -> fmt::Result {
f.debug_struct(name)
.field("type_name", &meta.type_name())
.field("kind", &meta.kind())
.finish()
}
impl dyn Meta + '_ {
pub fn to_ref<T: 'static>(&self) -> Option<&T> {
self.as_any().downcast_ref::<T>()
}
pub fn is<T: 'static>(&self) -> bool {
self.as_any().is::<T>()
}
pub fn visit_map_entries(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
Meta::visit_map_entries(self, visitor)
}
pub fn field_path<'a, Q: FieldPathQuery<'a>>(&'a self, query: Q) -> Option<Q::Output> {
ObjectRef::new(self).field_path(query)
}
}
impl PartialEq for dyn Meta + '_ {
fn eq(&self, other: &Self) -> bool {
self.eq_dyn(other)
}
}
#[derive(Clone, Copy)]
pub struct ObjectRef<'a> {
inner: &'a dyn Meta,
}
impl<'a> ObjectRef<'a> {
pub fn new(inner: &'a dyn Meta) -> Self {
ObjectRef { inner }
}
pub fn as_meta(&self) -> &'a dyn Meta {
self.inner
}
pub fn type_info(&self) -> TypeInfo {
self.inner.type_info()
}
pub fn type_name(&self) -> &'static str {
self.inner.type_name()
}
pub fn id(&self) -> core::any::TypeId {
self.inner.id()
}
pub fn kind(&self) -> ValueKind {
self.inner.kind()
}
pub fn access_kind(&self) -> Option<AccessKind> {
self.inner.access_kind()
}
pub fn option_value(&self) -> Option<ObjectRef<'a>> {
self.inner.option_value()
}
pub fn field(&self, name: &str) -> Option<ObjectRef<'a>> {
self.inner.field(name)
}
pub fn field_names(&self) -> &'static [&'static str] {
self.inner.field_names()
}
pub fn item(&self, index: usize) -> Option<ObjectRef<'a>> {
self.inner.item(index)
}
pub fn len(&self) -> Option<usize> {
self.inner.len()
}
pub fn is_empty(&self) -> Option<bool> {
self.inner.is_empty()
}
pub fn key(&self, key: &str) -> Option<ObjectRef<'a>> {
self.inner.key(key)
}
pub fn keys(&self) -> Option<Vec<String>> {
self.inner.keys()
}
pub fn visit_map_entries(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
Meta::visit_map_entries(self.inner, visitor)
}
pub fn to_ref<T: 'static>(&self) -> Option<&'a T> {
self.inner.as_any().downcast_ref::<T>()
}
pub fn is<T: 'static>(&self) -> bool {
self.inner.as_any().is::<T>()
}
pub fn eq_dyn(&self, other: ObjectRef<'_>) -> bool {
self.inner.eq_dyn(other.inner)
}
pub fn field_path<Q: FieldPathQuery<'a>>(&self, query: Q) -> Option<Q::Output> {
query.resolve(*self)
}
}
impl fmt::Debug for ObjectRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "ObjectRef", self.inner)
}
}
impl PartialEq for ObjectRef<'_> {
fn eq(&self, other: &Self) -> bool {
self.inner.eq_dyn(other.inner)
}
}
#[repr(transparent)]
pub struct Object(Box<dyn Meta>);
impl Object {
pub fn new<T>(value: T) -> Self
where
T: Meta + 'static,
{
Self(Box::new(value))
}
pub fn into_inner(self) -> Box<dyn Meta> {
self.0
}
pub fn into_rc(self) -> Rc<dyn Meta> {
Rc::from(self.0)
}
}
impl From<Box<dyn Meta>> for Object {
fn from(value: Box<dyn Meta>) -> Self {
Self(value)
}
}
impl Deref for Object {
type Target = dyn Meta;
fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}
impl DerefMut for Object {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.as_mut()
}
}
impl AsRef<dyn Meta> for Object {
fn as_ref(&self) -> &(dyn Meta + 'static) {
self.0.as_ref()
}
}
impl AsMut<dyn Meta> for Object {
fn as_mut(&mut self) -> &mut (dyn Meta + 'static) {
self.0.as_mut()
}
}
impl fmt::Debug for Object {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "Object", self.0.as_ref())
}
}
impl PartialEq for Object {
fn eq(&self, other: &Self) -> bool {
Meta::eq_dyn(self.0.as_ref(), other.0.as_ref())
}
}
pub struct ObjectRefMut<'a> {
pub(crate) inner: &'a mut dyn MetaMut,
}
impl<'a> ObjectRefMut<'a> {
pub(crate) fn path_from<'b>(
current: &'b mut dyn MetaMut,
path: &[PathSegment<'_>],
) -> Option<ObjectRefMut<'b>> {
let Some((segment, rest)) = path.split_first() else {
return Some(ObjectRefMut::new(current));
};
let child = match segment {
PathSegment::Field(name) => current.field_mut(name)?,
PathSegment::Item(index) => current.item_mut(*index)?,
PathSegment::Key(key) => current.key_mut(key)?,
};
Self::path_from(child.inner, rest)
}
pub fn new(inner: &'a mut dyn MetaMut) -> Self {
Self { inner }
}
pub fn type_info(&self) -> TypeInfo {
self.inner.type_info()
}
pub fn type_name(&self) -> &'static str {
self.inner.type_name()
}
pub fn id(&self) -> core::any::TypeId {
self.inner.id()
}
pub fn kind(&self) -> ValueKind {
self.inner.kind()
}
pub fn access_kind(&self) -> Option<AccessKind> {
self.inner.access_kind()
}
pub fn field_names(&self) -> &'static [&'static str] {
self.inner.field_names()
}
pub fn len(&self) -> Option<usize> {
self.inner.len()
}
pub fn is_empty(&self) -> Option<bool> {
self.inner.is_empty()
}
pub fn keys(&self) -> Option<Vec<String>> {
self.inner.keys()
}
pub fn is<T: 'static>(&self) -> bool {
self.inner.as_any().is::<T>()
}
pub fn eq_dyn(&self, other: &ObjectRefMut<'_>) -> bool {
self.inner.as_meta().eq_dyn(other.inner.as_meta())
}
pub fn field_mut(&mut self, name: &str) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.field_mut(name)
.ok_or(ReflectiveError::PathNotFound)
}
pub fn item_mut(&mut self, index: usize) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.item_mut(index)
.ok_or(ReflectiveError::PathNotFound)
}
pub fn key_mut(&mut self, key: &str) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self.inner.key_mut(key).ok_or(ReflectiveError::PathNotFound)
}
pub fn insert_key(
&mut self,
key: &str,
value: Object,
) -> Result<ObjectRefMut<'_>, ReflectiveError> {
let child = self
.inner
.insert_key(key, value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)?;
Ok(child)
}
pub fn insert_item(
&mut self,
index: usize,
value: Object,
) -> Result<ObjectRefMut<'_>, ReflectiveError> {
let child = self
.inner
.insert_item(index, value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)?;
Ok(child)
}
pub fn push_item(&mut self, value: Object) -> Result<ObjectRefMut<'_>, ReflectiveError> {
let child = self
.inner
.push_item(value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)?;
Ok(child)
}
pub fn remove_key(&mut self, key: &str) -> Result<Object, ReflectiveError> {
let removed = self
.inner
.remove_key(key)
.ok_or(ReflectiveError::PathNotFound)?;
Ok(removed)
}
pub fn remove_item(&mut self, index: usize) -> Result<Object, ReflectiveError> {
let removed = self
.inner
.remove_item(index)
.ok_or(ReflectiveError::PathNotFound)?;
Ok(removed)
}
pub fn set(self, value: Object) -> Result<(), ReflectiveError> {
self
.inner
.set(value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)?;
Ok(())
}
pub fn replace(&mut self, value: Object) -> Result<Object, ReflectiveError> {
self
.inner
.replace(value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)
}
pub fn apply<'p, I>(&mut self, operations: I) -> Result<(), ApplyError<'p>>
where
I: IntoIterator<Item = PatchOperation<'p>>,
{
apply_patch(self.inner, operations)
}
pub fn to_mut<T: 'static>(self) -> Result<&'a mut T, ReflectiveError> {
let value = self
.inner
.as_any_mut()
.downcast_mut::<T>()
.ok_or(ReflectiveError::MutationTypeMismatch)?;
Ok(value)
}
pub fn field_path_mut<'r, Q>(&'r mut self, query: Q) -> Result<Q::Output, ReflectiveError>
where
Q: FieldPathQueryMut<'r>,
{
query.resolve(ObjectRefMut {
inner: &mut *self.inner,
})
}
pub fn set_field_path<'r, Q>(
&'r mut self,
query: Q,
value: Q::Value,
) -> Result<(), ReflectiveError>
where
Q: FieldPathQueryMut<'r>,
{
query.assign(
ObjectRefMut {
inner: &mut *self.inner,
},
value,
)
}
}
impl fmt::Debug for ObjectRefMut<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "ObjectRefMut", self.inner.as_meta())
}
}
impl PartialEq for ObjectRefMut<'_> {
fn eq(&self, other: &Self) -> bool {
self.eq_dyn(other)
}
}
#[repr(transparent)]
pub struct ObjectMut(Box<dyn MetaMut>);
struct MetaMutObject(Box<dyn MetaMut>);
impl fmt::Debug for MetaMutObject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "MetaMutObject", self.0.as_meta())
}
}
impl Meta for MetaMutObject {
fn type_info(&self) -> TypeInfo {
self.0.type_info()
}
fn kind(&self) -> ValueKind {
self.0.kind()
}
fn access_kind(&self) -> Option<AccessKind> {
self.0.access_kind()
}
fn option_value(&self) -> Option<ObjectRef<'_>> {
self.0.option_value()
}
fn field(&self, name: &str) -> Option<ObjectRef<'_>> {
self.0.field(name)
}
fn field_names(&self) -> &'static [&'static str] {
self.0.field_names()
}
fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
self.0.item(index)
}
fn len(&self) -> Option<usize> {
self.0.len()
}
fn is_empty(&self) -> Option<bool> {
self.0.is_empty()
}
fn key(&self, key: &str) -> Option<ObjectRef<'_>> {
self.0.key(key)
}
fn keys(&self) -> Option<Vec<String>> {
self.0.keys()
}
fn visit_map_entries(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
self.0.visit_map_entries(visitor)
}
fn eq_dyn(&self, other: &dyn Meta) -> bool {
self.0.eq_dyn(other)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
let MetaMutObject(inner) = *self;
Meta::into_any(inner)
}
fn as_any(&self) -> &dyn Any {
Meta::as_any(self.0.as_ref())
}
}
impl ObjectMut {
pub fn new<T>(value: T) -> Self
where
T: MetaMut + 'static,
{
Self(Box::new(value))
}
pub fn from_clone<T>(value: &T) -> Self
where
T: MetaMut + Clone + 'static,
{
Self::new(value.clone())
}
pub fn into_inner(self) -> Box<dyn MetaMut> {
self.0
}
pub fn into_object(self) -> Object {
Object::new(MetaMutObject(self.0))
}
}
impl From<Box<dyn MetaMut>> for ObjectMut {
fn from(value: Box<dyn MetaMut>) -> Self {
Self(value)
}
}
impl From<ObjectMut> for Object {
fn from(value: ObjectMut) -> Self {
value.into_object()
}
}
impl Deref for ObjectMut {
type Target = dyn MetaMut;
fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}
impl DerefMut for ObjectMut {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.as_mut()
}
}
impl AsRef<dyn MetaMut> for ObjectMut {
fn as_ref(&self) -> &(dyn MetaMut + 'static) {
self.0.as_ref()
}
}
impl AsMut<dyn MetaMut> for ObjectMut {
fn as_mut(&mut self) -> &mut (dyn MetaMut + 'static) {
self.0.as_mut()
}
}
impl fmt::Debug for ObjectMut {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "ObjectMut", self.0.as_meta())
}
}
pub trait SendMeta: Meta + Send + Sync {
fn into_object(self: Box<Self>) -> Object;
}
impl<T> SendMeta for T
where
T: Meta + Send + Sync + 'static,
{
fn into_object(self: Box<Self>) -> Object {
Object::new(*self)
}
}
#[repr(transparent)]
pub struct SendObject(Box<dyn SendMeta>);
impl SendObject {
pub fn new<T>(value: T) -> Self
where
T: Meta + Send + Sync + 'static,
{
Self(Box::new(value))
}
pub fn into_inner(self) -> Box<dyn SendMeta> {
self.0
}
pub fn into_object(self) -> Object {
SendMeta::into_object(self.0)
}
}
impl From<Box<dyn SendMeta>> for SendObject {
fn from(value: Box<dyn SendMeta>) -> Self {
Self(value)
}
}
impl Deref for SendObject {
type Target = dyn SendMeta;
fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}
impl AsRef<dyn SendMeta> for SendObject {
fn as_ref(&self) -> &(dyn SendMeta + 'static) {
self.0.as_ref()
}
}
impl fmt::Debug for SendObject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "SendObject", self.0.as_ref())
}
}
pub trait ObjectOps {
fn is<T: 'static>(&self) -> bool;
fn to<T: 'static>(self) -> Result<T, Object>;
fn to_ref<T: 'static>(&self) -> Option<&T>;
}
impl ObjectOps for Object {
fn is<T: 'static>(&self) -> bool {
self.0.as_any().is::<T>()
}
fn to<T: 'static>(self) -> Result<T, Object> {
if self.is::<T>() {
Ok(*self.into_inner().into_any().downcast::<T>().unwrap())
} else {
Err(self)
}
}
fn to_ref<T: 'static>(&self) -> Option<&T> {
self.0.as_any().downcast_ref::<T>()
}
}
impl ObjectOps for SendObject {
fn is<T: 'static>(&self) -> bool {
self.0.as_ref().as_any().is::<T>()
}
fn to<T: 'static>(self) -> Result<T, Object> {
if self.is::<T>() {
Ok(*Meta::into_any(self.0).downcast::<T>().unwrap())
} else {
Err(SendMeta::into_object(self.0))
}
}
fn to_ref<T: 'static>(&self) -> Option<&T> {
self.as_ref().as_any().downcast_ref::<T>()
}
}