//! Impls for references `&T` and `&mut T`.
//!
//! ## Walk
//!
//! `&T` implements [`WalkOnce`], [`WalkMut`], and [`Walk`] if `T` implements [`Walk`].
//!
//! `&mut T` implements [`WalkOnce`], and [`WalkMut`] if `T` implements [`WalkMut`].
//!
//! ## Build
// === &T ===
use core::{any::Any, marker::PhantomData};
use crate::{
build::{Build, Builder},
error::{Missing, UniError, WalkerError, WrongProtocol},
protocol::{AnyVisit, ProtocolId, Visit},
protocol_list,
protocols::reference::{self, Reference},
walk::{Walk, WalkMut, WalkOnce},
};
impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> WalkOnce<'value, 'ctx, VisitorErr>
for &'ctx T
where
T: Walk<'value, 'ctx, VisitorErr>,
{
type ErrorOnce = T::Error;
type WalkerOnce = T::Walker;
fn into_walker(self) -> T::Walker {
T::walker(self)
}
}
impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> WalkMut<'value, 'ctx, VisitorErr>
for &'ctx T
where
T: Walk<'value, 'ctx, VisitorErr>,
{
type ErrorMut = T::Error;
type WalkerMut = T::Walker;
fn walker_mut(&'value mut self) -> T::Walker {
T::walker(*self)
}
}
impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> Walk<'value, 'ctx, VisitorErr> for &'ctx T
where
T: Walk<'value, 'ctx, VisitorErr>,
{
type Error = T::Error;
type Walker = T::Walker;
fn walker(&'value self) -> Self::Walker {
T::walker(self)
}
}
/// Error when building a reference.
///
/// References can only be built if the walker gives a
/// long enough lifetime reference. See the [`Reference`]
/// protocol.
#[derive(thiserror::Error, Debug)]
pub enum ShortLifetime {
/// The walker gave a `'walking` lifetime reference
/// but a longer lifetime was needed.
#[error("got `'walking` lifetime")]
Walking,
/// The walker gave a `'value` lifetime reference
/// but a longer lifetime was needed.
#[error("got `'value` lifetime")]
Value,
/// The walker gave a `'context` lifetime reference
/// but a longer lifetime was needed.
#[error("got `'ctx` lifetime")]
Context,
}
#[derive(Debug)]
pub struct BuilderRefValue<'value, T: ?Sized>(Option<&'value T>);
impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Build<'value, 'ctx, WalkerErr>
for &'value T
{
type Error = Missing<WrongProtocol<ShortLifetime>>;
type Builder = BuilderRefValue<'value, T>;
}
impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Builder<'value, 'ctx, WalkerErr>
for BuilderRefValue<'value, T>
{
type Error = Missing<WrongProtocol<ShortLifetime>>;
type Value = &'value T;
fn init() -> Self
where
Self: Sized,
{
Self(None)
}
fn as_visitor(
&mut self,
) -> &mut dyn crate::Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
self
}
fn finish(self) -> Result<Self::Value, crate::error::UniError<WalkerErr, Self::Error>>
where
Self: Sized,
{
self.0.ok_or(UniError::Visitor(Missing::Missing))
}
}
impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any>
crate::Visitor<'value, 'ctx, WalkerErr> for BuilderRefValue<'value, T>
{
type Error = Missing<WrongProtocol<ShortLifetime>>;
fn protocol(
&mut self,
id: crate::protocol::ProtocolId,
) -> Option<crate::protocol::AnyVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
match id {
id if id == ProtocolId::of::<Reference<T>>() => Some(AnyVisit::new(self)),
_ => None,
}
}
fn all_protocols() -> impl Iterator<Item = crate::protocol::ProtocolDescription>
where
Self: Sized,
{
protocol_list![Reference<T>]
}
}
impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any>
Visit<'value, 'ctx, Reference<T>, WalkerErr> for BuilderRefValue<'value, T>
{
type Error = Missing<WrongProtocol<ShortLifetime>>;
fn visit<'walking>(
&'walking mut self,
accessor: <Reference<T> as crate::protocol::Protocol<'value, 'ctx>>::Accessor<
'walking,
WalkerErr,
Self::Error,
>,
) -> Result<(), UniError<WalkerErr, Self::Error>> {
use reference::Ref::*;
match accessor {
Walking(_) => Err(UniError::Visitor(Missing::Error(WrongProtocol::Error(
ShortLifetime::Walking,
)))),
Value(value) | Context(value) | Static(value) => {
self.0 = Some(value);
Ok(())
}
}
}
}
// === &mut T ===
impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T> WalkOnce<'value, 'ctx, VisitorErr> for &'ctx mut T
where
T: WalkMut<'value, 'ctx, VisitorErr>,
{
type ErrorOnce = T::ErrorMut;
type WalkerOnce = T::WalkerMut;
fn into_walker(self) -> T::WalkerMut {
T::walker_mut(self)
}
}
impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T> WalkMut<'value, 'ctx, VisitorErr> for &'ctx mut T
where
T: WalkMut<'value, 'ctx, VisitorErr>,
{
type ErrorMut = T::ErrorMut;
type WalkerMut = T::WalkerMut;
fn walker_mut(&'value mut self) -> T::WalkerMut {
T::walker_mut(self)
}
}