#[allow(unused_imports)]
use crate::{
AccessKind, ApplyError, EnumAccess, FieldPathQuery, FieldPathQueryMut, MapAccessMut,
MapEntryVisitor, Meta, MetaMut, MoveItemError, MutationBatch, PatchOperation, PathSegment,
Reflect, ReflectMut, ReflectiveError, SequenceAccessMut, TypeInfo, TypedPath, ValueKind,
VariantFields, apply_patch,
};
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
#[cfg(not(typex_trait_upcasting))]
use core::any::Any;
use core::fmt;
fn fmt_meta(f: &mut fmt::Formatter<'_>, name: &str, meta: &dyn Meta) -> fmt::Result {
let view = ObjectRef::new(meta);
f.debug_struct(name)
.field("type_name", &view.type_name())
.field("kind", &view.kind())
.finish()
}
#[derive(Clone, Copy)]
pub struct ObjectRef<'a> {
inner: &'a dyn Meta,
}
#[inline(never)]
pub(crate) fn select_variant<'b>(
current: &'b mut dyn MetaMut,
name: &str,
) -> Option<&'b mut dyn MetaMut> {
match current.is_variant_dyn(name) {
Some(true) => Some(current),
Some(false) => None,
None => select_option_variant(current, name),
}
}
#[inline(never)]
fn select_option_variant<'b>(
current: &'b mut dyn MetaMut,
name: &str,
) -> Option<&'b mut dyn MetaMut> {
match current.reflect_mut() {
ReflectMut::Option(value) => select_variant(value.value_mut()?.inner, name),
_ => None,
}
}
impl<'a> ObjectRef<'a> {
#[inline]
pub fn new(inner: &'a dyn Meta) -> Self {
ObjectRef { inner }
}
#[inline]
pub fn as_meta(&self) -> &'a dyn Meta {
self.inner
}
#[inline]
pub fn type_info(&self) -> TypeInfo {
self.inner.type_info()
}
#[inline]
pub fn type_name(&self) -> &'static str {
self.inner.type_info().name()
}
#[inline]
pub fn type_id(&self) -> core::any::TypeId {
self.inner.type_info().id()
}
#[inline]
pub fn kind(&self) -> ValueKind {
self.inner.kind_dyn()
}
#[inline]
pub fn access_kind(&self) -> Option<AccessKind> {
self.inner.access_kind_dyn()
}
#[inline]
pub fn option_value(&self) -> Option<ObjectRef<'a>> {
match self.inner.reflect() {
Reflect::Option(value) => value,
_ => None,
}
}
#[inline]
pub fn variant(&self, name: &str) -> Option<ObjectRef<'a>> {
match self.inner.is_variant_dyn(name) {
Some(true) => Some(*self),
Some(false) => None,
None => self.option_variant(name),
}
}
#[inline(never)]
fn option_variant(&self, name: &str) -> Option<ObjectRef<'a>> {
self.option_value()?.variant(name)
}
#[inline]
pub fn variant_name(&self) -> Option<&'static str> {
match self.inner.reflect() {
Reflect::Enum(value) => Some(value.variant_name()),
Reflect::Option(value) => value?.variant_name(),
_ => None,
}
}
#[inline]
pub fn field(&self, name: &str) -> Option<ObjectRef<'a>> {
self.inner.field_dyn(name)
}
#[inline]
pub fn field_names(&self) -> &'static [&'static str] {
self.inner.field_names_dyn()
}
#[inline]
pub fn item(&self, index: usize) -> Option<ObjectRef<'a>> {
self.inner.item_dyn(index)
}
#[inline]
pub fn len(&self) -> Option<usize> {
self.inner.len_dyn()
}
#[inline]
pub fn is_empty(&self) -> Option<bool> {
self.len().map(|len| len == 0)
}
#[inline]
pub fn key(&self, key: &str) -> Option<ObjectRef<'a>> {
self.inner.key_dyn(key)
}
#[inline]
pub fn keys(&self) -> Option<Vec<String>> {
match self.inner.reflect() {
Reflect::Map(value) => value.keys(),
Reflect::KeyedSequence(value) => Some(value.keys()),
Reflect::Option(value) => value?.keys(),
_ => None,
}
}
#[inline]
pub fn visit_map_entries(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
self.inner.visit_map_entries_dyn(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 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<'_> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner.eq_dyn(other.inner)
}
}
macro_rules! forward_object_reads {
($ty:ty) => {
impl $ty {
#[inline]
pub fn type_info(&self) -> TypeInfo {
self.as_object_ref().type_info()
}
#[inline]
pub fn type_name(&self) -> &'static str {
self.as_object_ref().type_name()
}
#[inline]
pub fn type_id(&self) -> core::any::TypeId {
self.as_object_ref().type_id()
}
#[inline]
pub fn kind(&self) -> ValueKind {
self.as_object_ref().kind()
}
#[inline]
pub fn access_kind(&self) -> Option<AccessKind> {
self.as_object_ref().access_kind()
}
#[inline]
pub fn option_value(&self) -> Option<ObjectRef<'_>> {
self.as_object_ref().option_value()
}
#[inline]
pub fn variant(&self, name: &str) -> Option<ObjectRef<'_>> {
self.as_object_ref().variant(name)
}
#[inline]
pub fn variant_name(&self) -> Option<&'static str> {
self.as_object_ref().variant_name()
}
#[inline]
pub fn field(&self, name: &str) -> Option<ObjectRef<'_>> {
self.as_object_ref().field(name)
}
#[inline]
pub fn field_names(&self) -> &'static [&'static str] {
self.as_object_ref().field_names()
}
#[inline]
pub fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
self.as_object_ref().item(index)
}
#[inline]
pub fn len(&self) -> Option<usize> {
self.as_object_ref().len()
}
#[inline]
pub fn is_empty(&self) -> Option<bool> {
self.as_object_ref().is_empty()
}
#[inline]
pub fn key(&self, key: &str) -> Option<ObjectRef<'_>> {
self.as_object_ref().key(key)
}
#[inline]
pub fn keys(&self) -> Option<Vec<String>> {
self.as_object_ref().keys()
}
#[inline]
pub fn visit_map_entries(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
self.as_object_ref().visit_map_entries(visitor)
}
pub fn field_path<'s, Q: FieldPathQuery<'s>>(&'s self, query: Q) -> Option<Q::Output> {
self.as_object_ref().field_path(query)
}
}
};
}
forward_object_reads!(Object);
forward_object_reads!(ObjectRefMut<'_>);
forward_object_reads!(ObjectMut);
forward_object_reads!(SendObject);
#[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))
}
#[inline]
pub fn into_inner(self) -> Box<dyn Meta> {
self.0
}
#[inline]
pub fn as_object_ref(&self) -> ObjectRef<'_> {
ObjectRef::new(self.0.as_ref())
}
}
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 {
#[inline]
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> {
#[inline]
pub(crate) fn path_from<'b>(
mut current: &'b mut dyn MetaMut,
mut path: &[PathSegment<'_>],
) -> Option<ObjectRefMut<'b>> {
while let Some((segment, rest)) = path.split_first() {
current = match segment {
PathSegment::Field(name) => current.field_mut_dyn(name)?.inner,
PathSegment::Item(index) => current.item_mut_dyn(*index)?.inner,
PathSegment::Key(key) => current.key_mut_dyn(key)?.inner,
PathSegment::Variant(name) => return Self::path_from_variant(current, name, rest),
};
path = rest;
}
Some(ObjectRefMut::new(current))
}
#[inline(never)]
fn path_from_variant<'b>(
current: &'b mut dyn MetaMut,
name: &str,
rest: &[PathSegment<'_>],
) -> Option<ObjectRefMut<'b>> {
let current = match current.is_variant_dyn(name) {
Some(true) => current,
_ => select_option_variant(current, name)?,
};
Self::path_from(current, rest)
}
#[inline]
pub fn new(inner: &'a mut dyn MetaMut) -> Self {
Self { inner }
}
#[inline]
pub fn as_object_ref(&self) -> ObjectRef<'_> {
#[cfg(typex_trait_upcasting)]
{
ObjectRef::new(self.inner)
}
#[cfg(not(typex_trait_upcasting))]
{
ObjectRef::new(self.inner.as_meta())
}
}
pub fn is<T: 'static>(&self) -> bool {
self.inner.as_any().is::<T>()
}
#[inline]
pub fn field_mut(&mut self, name: &str) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.field_mut_dyn(name)
.ok_or(ReflectiveError::PathNotFound)
}
#[inline]
pub fn variant_mut(&mut self, name: &str) -> Result<ObjectRefMut<'_>, ReflectiveError> {
select_variant(self.inner, name)
.map(ObjectRefMut::new)
.ok_or(ReflectiveError::PathNotFound)
}
#[inline]
pub fn item_mut(&mut self, index: usize) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.item_mut_dyn(index)
.ok_or(ReflectiveError::PathNotFound)
}
#[inline]
pub fn key_mut(&mut self, key: &str) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.key_mut_dyn(key)
.ok_or(ReflectiveError::PathNotFound)
}
#[inline]
pub fn insert_key(
&mut self,
key: &str,
value: Object,
) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.insert_key_dyn(key, value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)
}
#[inline]
pub fn insert_item(
&mut self,
index: usize,
value: Object,
) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.insert_item_dyn(index, value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)
}
#[inline]
pub fn push_item(&mut self, value: Object) -> Result<ObjectRefMut<'_>, ReflectiveError> {
self
.inner
.push_item_dyn(value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)
}
#[inline]
pub fn remove_key(&mut self, key: &str) -> Result<Object, ReflectiveError> {
self
.inner
.remove_key_dyn(key)
.ok_or(ReflectiveError::PathNotFound)
}
#[inline]
pub fn remove_item(&mut self, index: usize) -> Result<Object, ReflectiveError> {
self
.inner
.remove_item_dyn(index)
.ok_or(ReflectiveError::PathNotFound)
}
#[inline]
pub fn move_item(&mut self, from: usize, to: usize) -> Result<(), MoveItemError> {
self.inner.move_item_dyn(from, to)
}
#[inline]
pub fn set(self, value: Object) -> Result<(), ReflectiveError> {
self
.inner
.set_dyn(value)
.map_err(|_| ReflectiveError::MutationTypeMismatch)
}
#[inline]
pub fn replace(&mut self, value: Object) -> Result<Object, ReflectiveError> {
self
.inner
.replace_dyn(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> {
self
.inner
.as_any_mut()
.downcast_mut::<T>()
.ok_or(ReflectiveError::MutationTypeMismatch)
}
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<'a> From<ObjectRefMut<'a>> for ObjectRef<'a> {
fn from(value: ObjectRefMut<'a>) -> Self {
let inner: &'a dyn MetaMut = value.inner;
#[cfg(typex_trait_upcasting)]
{
ObjectRef::new(inner)
}
#[cfg(not(typex_trait_upcasting))]
{
ObjectRef::new(inner.as_meta())
}
}
}
impl fmt::Debug for ObjectRefMut<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "ObjectRefMut", self.as_object_ref().as_meta())
}
}
impl PartialEq for ObjectRefMut<'_> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner.eq_dyn(other.as_object_ref().as_meta())
}
}
#[repr(transparent)]
pub struct ObjectMut(Box<dyn MetaMut>);
#[cfg(not(typex_trait_upcasting))]
struct MetaMutObject(Box<dyn MetaMut>);
#[cfg(not(typex_trait_upcasting))]
impl fmt::Debug for MetaMutObject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "MetaMutObject", self.0.as_meta())
}
}
#[cfg(not(typex_trait_upcasting))]
impl Meta for MetaMutObject {
fn type_info(&self) -> TypeInfo {
self.0.type_info()
}
fn reflect(&self) -> Reflect<'_> {
self.0.reflect()
}
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())
}
#[inline]
pub fn into_inner(self) -> Box<dyn MetaMut> {
self.0
}
#[inline]
pub fn into_object(self) -> Object {
#[cfg(typex_trait_upcasting)]
{
Object(self.0)
}
#[cfg(not(typex_trait_upcasting))]
{
Object::new(MetaMutObject(self.0))
}
}
#[inline]
pub fn as_object_ref(&self) -> ObjectRef<'_> {
#[cfg(typex_trait_upcasting)]
{
ObjectRef::new(self.0.as_ref())
}
#[cfg(not(typex_trait_upcasting))]
{
ObjectRef::new(self.0.as_meta())
}
}
#[inline]
pub fn as_object_ref_mut(&mut self) -> ObjectRefMut<'_> {
ObjectRefMut::new(self.0.as_mut())
}
#[inline]
pub fn field_mut(&mut self, name: &str) -> Option<ObjectRefMut<'_>> {
self.0.field_mut_dyn(name)
}
#[inline]
pub fn variant_mut(&mut self, name: &str) -> Option<ObjectRefMut<'_>> {
select_variant(self.0.as_mut(), name).map(ObjectRefMut::new)
}
#[inline]
pub fn item_mut(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
self.0.item_mut_dyn(index)
}
#[inline]
pub fn key_mut(&mut self, key: &str) -> Option<ObjectRefMut<'_>> {
self.0.key_mut_dyn(key)
}
#[inline]
pub fn set(&mut self, value: Object) -> Result<(), Object> {
self.0.set_dyn(value)
}
#[inline]
pub fn replace(&mut self, value: Object) -> Result<Object, Object> {
self.0.replace_dyn(value)
}
pub fn to_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.0.as_any_mut().downcast_mut::<T>()
}
pub fn field_path_mut<'r, Q: FieldPathQueryMut<'r>>(
&'r mut self,
query: Q,
) -> Result<Q::Output, ReflectiveError> {
query.resolve(self.as_object_ref_mut())
}
#[inline]
pub fn insert_key(&mut self, key: &str, value: Object) -> Result<ObjectRefMut<'_>, Object> {
self.0.insert_key_dyn(key, value)
}
#[inline]
pub fn insert_item(&mut self, index: usize, value: Object) -> Result<ObjectRefMut<'_>, Object> {
self.0.insert_item_dyn(index, value)
}
#[inline]
pub fn push_item(&mut self, value: Object) -> Result<ObjectRefMut<'_>, Object> {
self.0.push_item_dyn(value)
}
#[inline]
pub fn remove_key(&mut self, key: &str) -> Option<Object> {
self.0.remove_key_dyn(key)
}
#[inline]
pub fn remove_item(&mut self, index: usize) -> Option<Object> {
self.0.remove_item_dyn(index)
}
#[inline]
pub fn move_item(&mut self, from: usize, to: usize) -> Result<(), MoveItemError> {
self.0.move_item_dyn(from, to)
}
pub fn apply<'p, I>(&mut self, operations: I) -> Result<(), ApplyError<'p>>
where
I: IntoIterator<Item = PatchOperation<'p>>,
{
apply_patch(self.0.as_mut(), operations)
}
}
impl From<ObjectMut> for Object {
fn from(value: ObjectMut) -> Self {
value.into_object()
}
}
impl fmt::Debug for ObjectMut {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "ObjectMut", self.as_object_ref().as_meta())
}
}
pub trait SendMeta: Meta + Send + Sync {
fn into_object(self: Box<Self>) -> Object;
#[doc(hidden)]
fn as_meta(&self) -> &dyn Meta;
}
impl<T> SendMeta for T
where
T: Meta + Send + Sync + 'static,
{
fn into_object(self: Box<Self>) -> Object {
Object(self)
}
fn as_meta(&self) -> &dyn Meta {
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))
}
#[inline]
pub fn into_inner(self) -> Box<dyn SendMeta> {
self.0
}
#[inline]
pub fn into_object(self) -> Object {
#[cfg(typex_trait_upcasting)]
{
Object(self.0)
}
#[cfg(not(typex_trait_upcasting))]
{
SendMeta::into_object(self.0)
}
}
#[inline]
pub fn as_object_ref(&self) -> ObjectRef<'_> {
#[cfg(typex_trait_upcasting)]
{
ObjectRef::new(self.0.as_ref())
}
#[cfg(not(typex_trait_upcasting))]
{
ObjectRef::new(self.0.as_meta())
}
}
}
impl From<SendObject> for Object {
fn from(value: SendObject) -> Self {
value.into_object()
}
}
impl fmt::Debug for SendObject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_meta(f, "SendObject", self.as_object_ref().as_meta())
}
}
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 ObjectMut {
#[inline]
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(*Meta::into_any(self.0).downcast::<T>().unwrap())
} else {
Err(self.into_object())
}
}
#[inline]
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_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(self.into_object())
}
}
fn to_ref<T: 'static>(&self) -> Option<&T> {
self.0.as_any().downcast_ref::<T>()
}
}