use core::{any::Any, marker::PhantomData};
use crate::{
build::{Build, Builder},
error::{Missing, PrimitiveTypeError, UniError},
protocol::{lookup_visit, AnyProtocolVisit, AnyVisit, ProtocolDescription, ProtocolId, Visit},
protocols::reference,
walk::{Walk, WalkMut, WalkOnce},
Fallible, Visitor, WalkStatus, Walker,
};
pub trait LifetimeBound {}
pub enum ValueLifetime {}
pub enum ContextLifetime {}
pub enum StaticLifetime {}
impl LifetimeBound for ValueLifetime {}
impl LifetimeBound for ContextLifetime {}
impl LifetimeBound for StaticLifetime {}
pub struct RefWalker<'a, T: ?Sized, Lt: LifetimeBound>(&'a T, PhantomData<Lt>);
impl<'a, T: ?Sized, Lt: LifetimeBound> RefWalker<'a, T, Lt> {
pub fn new(value: &'a T) -> Self {
Self(value, PhantomData)
}
}
impl<'ctx, T: ?Sized, Lt: LifetimeBound> Fallible for RefWalker<'ctx, T, Lt> {
type Error = PrimitiveTypeError;
}
impl<'value, 'borrow: 'value, 'ctx: 'borrow, T: ?Sized + Any, VisitorErr: 'value>
Walker<'value, 'ctx, VisitorErr> for RefWalker<'borrow, T, ValueLifetime>
{
fn walk(
&mut self,
visitor: &mut dyn Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>,
) -> Result<WalkStatus, UniError<Self::Error, VisitorErr>> {
let mut protocol =
lookup_visit::<reference::Reference<T>, _, _>(visitor).map_err(UniError::Walker)?;
protocol.visit(reference::Ref::Value(self.0))?;
Ok(WalkStatus::Repeat)
}
}
impl<'value, 'ctx: 'value, 'borrow: 'ctx, T: ?Sized + Any, VisitorErr: 'value>
Walker<'value, 'ctx, VisitorErr> for RefWalker<'borrow, T, ContextLifetime>
{
fn walk(
&mut self,
visitor: &mut dyn Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>,
) -> Result<WalkStatus, UniError<Self::Error, VisitorErr>> {
let mut protocol =
lookup_visit::<reference::Reference<T>, _, _>(visitor).map_err(UniError::Walker)?;
protocol.visit(reference::Ref::Context(self.0))?;
Ok(WalkStatus::Repeat)
}
}
impl<'value, 'ctx: 'value, 'borrow: 'ctx, T: ?Sized + Any, VisitorErr: 'value>
Walker<'value, 'ctx, VisitorErr> for RefWalker<'static, T, StaticLifetime>
{
fn walk(
&mut self,
visitor: &mut dyn Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>,
) -> Result<WalkStatus, UniError<Self::Error, VisitorErr>> {
let mut protocol =
lookup_visit::<reference::Reference<T>, _, _>(visitor).map_err(UniError::Walker)?;
protocol.visit(reference::Ref::Static(self.0))?;
Ok(WalkStatus::Repeat)
}
}
impl<'value, 'borrow: 'value, 'ctx: 'borrow, T: ?Sized> WalkOnce<'value, 'ctx> for &'borrow T
where
T: Walk<'value, 'borrow, 'ctx>,
{
type Error = T::Error;
type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
fn into_walker<VisitorErr: 'value>(self) -> Self::Walker<VisitorErr> {
T::walker(self)
}
}
impl<'value, 'method: 'value, 'borrow: 'method, 'ctx: 'borrow, T: ?Sized>
WalkMut<'value, 'method, 'ctx> for &'borrow T
where
T: Walk<'value, 'borrow, 'ctx>,
{
type Error = T::Error;
type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
fn walker_mut<VisitorErr: 'value>(&'method mut self) -> Self::Walker<VisitorErr> {
T::walker(self)
}
}
impl<'value, 'method: 'value, 'borrow: 'method, 'ctx: 'borrow, T: ?Sized>
Walk<'value, 'method, 'ctx> for &'borrow T
where
T: Walk<'value, 'borrow, 'ctx>,
{
type Error = T::Error;
type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
fn walker<VisitorErr: 'value>(&'method self) -> Self::Walker<VisitorErr> {
T::walker(self)
}
}
impl<'value, 'borrow: 'value, 'ctx: 'borrow, T: ?Sized> WalkOnce<'value, 'ctx> for &'borrow mut T
where
T: WalkMut<'value, 'borrow, 'ctx>,
{
type Error = T::Error;
type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
fn into_walker<VisitorErr: 'value>(self) -> Self::Walker<VisitorErr> {
T::walker_mut(self)
}
}
impl<'value, 'borrow: 'value, 'ctx: 'borrow, T: ?Sized> WalkMut<'value, 'borrow, 'ctx>
for &'borrow mut T
where
T: WalkMut<'value, 'borrow, 'ctx>,
{
type Error = T::Error;
type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
fn walker_mut<VisitorErr: 'value>(&'borrow mut self) -> Self::Walker<VisitorErr> {
T::walker_mut(self)
}
}
#[derive(thiserror::Error, Debug)]
pub enum LifetimeIsShort<'value, 'ctx, T: ?Sized> {
Walking,
Value(&'value T),
Context(&'ctx T),
}
pub struct RefBuilder<'value, T: ?Sized, Lt: LifetimeBound>(Option<&'value T>, PhantomData<Lt>);
impl<'value, 'ctx: 'value, T: ?Sized + Any> Builder<'value, 'ctx>
for RefBuilder<'value, T, ValueLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
type Value = &'value T;
fn init() -> Self
where
Self: Sized,
{
Self(None, PhantomData)
}
fn as_visitor<WalkerErr: 'value>(
&mut self,
) -> &mut dyn Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
self
}
fn finish(self) -> Result<Self::Value, Self::Error>
where
Self: Sized,
{
if let Some(value) = self.0 {
Ok(value)
} else {
Err(Missing::Missing)
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr: 'value> Visitor<'value, 'ctx, WalkerErr>
for RefBuilder<'value, T, ValueLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn protocol(
&mut self,
id: ProtocolId,
) -> Option<AnyProtocolVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
match id {
id if id == ProtocolId::of::<reference::Reference<T>>() => {
Some(AnyVisit::new(self).erase())
}
_ => None,
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr>
Visit<'value, 'ctx, reference::Reference<T>, WalkerErr>
for RefBuilder<'value, T, ValueLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn visit<'walking>(
&'walking mut self,
accessor: reference::Ref<'walking, 'value, 'ctx, T>,
) -> Result<(), UniError<WalkerErr, Self::Error>> {
match accessor {
reference::Ref::Walking(_) => {
Err(UniError::Visitor(Missing::Error(LifetimeIsShort::Walking)))
}
reference::Ref::Value(value)
| reference::Ref::Context(value)
| reference::Ref::Static(value) => {
self.0 = Some(value);
Ok(())
}
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any> Builder<'value, 'ctx>
for RefBuilder<'ctx, T, ContextLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
type Value = &'ctx T;
fn init() -> Self
where
Self: Sized,
{
Self(None, PhantomData)
}
fn as_visitor<WalkerErr: 'value>(
&mut self,
) -> &mut dyn Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
self
}
fn finish(self) -> Result<Self::Value, Self::Error>
where
Self: Sized,
{
if let Some(value) = self.0 {
Ok(value)
} else {
Err(Missing::Missing)
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr: 'value> Visitor<'value, 'ctx, WalkerErr>
for RefBuilder<'ctx, T, ContextLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn protocol(
&mut self,
id: ProtocolId,
) -> Option<AnyProtocolVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
match id {
id if id == ProtocolId::of::<reference::Reference<T>>() => {
Some(AnyVisit::new(self).erase())
}
_ => None,
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr>
Visit<'value, 'ctx, reference::Reference<T>, WalkerErr>
for RefBuilder<'ctx, T, ContextLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn visit<'walking>(
&'walking mut self,
accessor: reference::Ref<'walking, 'value, 'ctx, T>,
) -> Result<(), UniError<WalkerErr, Self::Error>> {
match accessor {
reference::Ref::Walking(_) => {
Err(UniError::Visitor(Missing::Error(LifetimeIsShort::Walking)))
}
reference::Ref::Value(value) => Err(UniError::Visitor(Missing::Error(
LifetimeIsShort::Value(value),
))),
reference::Ref::Context(value) | reference::Ref::Static(value) => {
self.0 = Some(value);
Ok(())
}
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any> Builder<'value, 'ctx>
for RefBuilder<'static, T, StaticLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
type Value = &'static T;
fn init() -> Self
where
Self: Sized,
{
Self(None, PhantomData)
}
fn as_visitor<WalkerErr: 'value>(
&mut self,
) -> &mut dyn Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
self
}
fn finish(self) -> Result<Self::Value, Self::Error>
where
Self: Sized,
{
if let Some(value) = self.0 {
Ok(value)
} else {
Err(Missing::Missing)
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr: 'value> Visitor<'value, 'ctx, WalkerErr>
for RefBuilder<'static, T, StaticLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn protocol(
&mut self,
id: ProtocolId,
) -> Option<AnyProtocolVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
match id {
id if id == ProtocolId::of::<reference::Reference<T>>() => {
Some(AnyVisit::new(self).erase())
}
_ => None,
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr>
Visit<'value, 'ctx, reference::Reference<T>, WalkerErr>
for RefBuilder<'static, T, StaticLifetime>
{
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn visit<'walking>(
&'walking mut self,
accessor: reference::Ref<'walking, 'value, 'ctx, T>,
) -> Result<(), UniError<WalkerErr, Self::Error>> {
match accessor {
reference::Ref::Walking(_) => {
Err(UniError::Visitor(Missing::Error(LifetimeIsShort::Walking)))
}
reference::Ref::Value(value) => Err(UniError::Visitor(Missing::Error(
LifetimeIsShort::Value(value),
))),
reference::Ref::Context(value) => Err(UniError::Visitor(Missing::Error(
LifetimeIsShort::Context(value),
))),
reference::Ref::Static(value) => {
self.0 = Some(value);
Ok(())
}
}
}
}
impl<'value, 'ctx: 'value, T: ?Sized + Any> Build<'value, 'ctx> for &'value T {
type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
type Builder = RefBuilder<'value, T, ValueLifetime>;
}