mod error;
mod impls;
pub mod internals;
pub use error::{FieldError, FieldErrorKind};
pub use keypath_proc_macros::{keypath, Keyable};
use std::any::Any;
use std::borrow::Cow;
use std::marker::PhantomData;
pub struct KeyPath<Root: ?Sized, Value: 'static> {
partial: PartialKeyPath<Root>,
_value: PhantomData<Value>,
}
#[doc(hidden)]
#[derive(Debug)]
pub struct PartialKeyPath<Root: ?Sized> {
fields: Cow<'static, [internals::PathComponent]>,
_root: PhantomData<Root>,
}
impl<Root, Value> KeyPath<Root, Value> {
#[doc(hidden)]
pub const fn __conjure_from_abyss(fields: &'static [internals::PathComponent]) -> Self {
KeyPath {
partial: PartialKeyPath {
fields: Cow::Borrowed(fields),
_root: PhantomData,
},
_value: PhantomData,
}
}
pub fn append<T>(&self, other: &KeyPath<Value, T>) -> KeyPath<Root, T> {
let mut partial = self.partial.clone();
partial
.fields
.to_mut()
.extend(other.partial.fields.iter().clone());
KeyPath {
partial,
_value: other._value,
}
}
}
pub trait Keyable: internals::RawKeyable {
type Mirror;
fn mirror() -> Self::Mirror;
fn try_any_at_path(
&self,
path: impl AsRef<[internals::PathComponent]>,
) -> Result<&dyn Any, FieldError> {
self.get_field(path.as_ref())
.map(internals::RawKeyable::as_any)
}
fn try_any_at_path_mut(
&mut self,
path: impl AsRef<[internals::PathComponent]>,
) -> Result<&mut dyn Any, FieldError> {
self.get_field_mut(path.as_ref())
.map(internals::RawKeyable::as_any_mut)
}
#[doc(hidden)]
fn try_item_at_path<T>(&self, path: &KeyPath<Self, T>) -> Result<&T, FieldError> {
self.try_any_at_path(path)
.map(|t| t.downcast_ref().unwrap())
}
#[doc(hidden)]
fn try_item_at_path_mut<T>(&mut self, path: &KeyPath<Self, T>) -> Result<&mut T, FieldError> {
self.try_any_at_path_mut(path)
.map(|t| t.downcast_mut().unwrap())
}
fn item_at_path<T>(&self, path: &KeyPath<Self, T>) -> &T {
self.try_item_at_path(path).unwrap()
}
fn item_at_path_mut<T>(&mut self, path: &KeyPath<Self, T>) -> &mut T {
self.try_item_at_path_mut(path).unwrap()
}
}
impl<Root: ?Sized, Value: 'static> AsRef<[internals::PathComponent]> for KeyPath<Root, Value> {
fn as_ref(&self) -> &[internals::PathComponent] {
self.partial.fields.as_ref()
}
}
impl<R: ?Sized> Clone for PartialKeyPath<R> {
fn clone(&self) -> Self {
PartialKeyPath {
fields: self.fields.clone(),
_root: PhantomData,
}
}
}