Diffstat (limited to 'src/impls/core/reference.rs')
-rw-r--r--src/impls/core/reference.rs471
1 files changed, 270 insertions, 201 deletions
diff --git a/src/impls/core/reference.rs b/src/impls/core/reference.rs
index d1fe29e..69c8f08 100644
--- a/src/impls/core/reference.rs
+++ b/src/impls/core/reference.rs
@@ -1,139 +1,165 @@
-//! 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},
+ error::{Missing, PrimitiveTypeError, UniError},
+ protocol::{lookup_visit, AnyProtocolVisit, AnyVisit, ProtocolDescription, ProtocolId, Visit},
+ protocols::reference,
walk::{Walk, WalkMut, WalkOnce},
+ Fallible, Visitor, WalkStatus, Walker,
};
-// 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)
-// }
-// }
-
-// pub struct Error<'value, 'ctx, E>(E, PhantomData<&'value &'ctx ()>);
-//
-// impl<'value, 'ctx, E: WalkerError<'ctx, 'static>> WalkerError<'value, 'ctx> for Error<'value, 'ctx, E> {
-// fn wrong_visit<P: crate::protocol::Protocol<'value, 'ctx>>() -> Self {
-// todo!()
-// }
-//
-// fn needs_hint() -> Self {
-// todo!()
-// }
-// }
-//
-// pub struct Walker<'value, 'ctx, 'root, W>(W, PhantomData<&'value &'ctx &'root ()>);
-//
-// impl<'value, 'ctx: 'value, 'root: 'ctx, W: crate::Walker<'value, 'ctx, VisitorErr>, VisitorErr> crate::Walker<'value, 'ctx, VisitorErr> for Walker<'value, 'ctx, 'root, W>
-// {
-// type Error = Error<'value, 'ctx, 'root, W::Error>;
-//
-// fn walk(
-// &mut self,
-// visitor: &mut dyn crate::Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>,
-// ) -> Result<crate::WalkStatus, UniError<Self::Error, VisitorErr>> {
-// todo!()
-// }
-//
-// fn all_protocols() -> impl Iterator<Item = crate::protocol::ProtocolDescription>
-// where
-// Self: Sized {
-// W::all_protocols()
-// }
-// }
-
-/// `'value` and `'ctx` form the bounds of the possible lifetimes.
-/// These are what the walker will actually work with.
-///
-/// `'value`` < `'borrow` < `'ctx`
-/// `'borrow` allows &'value &'borrow T to forward to T's &'borrow T
-impl<'value, 'method: 'value, 'borrow: 'method, 'ctx: 'borrow, VisitorErr, T: ?Sized> Walk<'value, 'method, 'ctx, VisitorErr> for &'borrow T
+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, VisitorErr>,
+ T: Walk<'value, 'borrow, 'ctx>,
{
type Error = T::Error;
- type Walker = T::Walker;
- fn walker(&'method self) -> Self::Walker {
+ type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
+
+ fn walker_mut<VisitorErr: 'value>(&'method mut self) -> Self::Walker<VisitorErr> {
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,
+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;
- /// The walker gave a `'value` lifetime reference
- /// but a longer lifetime was needed.
- #[error("got `'value` lifetime")]
- Value,
+ type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>;
- /// The walker gave a `'context` lifetime reference
- /// but a longer lifetime was needed.
- #[error("got `'ctx` lifetime")]
- Context,
+ fn walker<VisitorErr: 'value>(&'method self) -> Self::Walker<VisitorErr> {
+ T::walker(self)
+ }
}
-#[derive(Debug)]
-pub struct BuilderRefValue<'value, T: ?Sized>(Option<&'value T>);
+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, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Build<'value, 'ctx, WalkerErr>
- for &'value T
+impl<'value, 'borrow: 'value, 'ctx: 'borrow, T: ?Sized> WalkMut<'value, 'borrow, 'ctx>
+ for &'borrow mut T
+where
+ T: WalkMut<'value, 'borrow, 'ctx>,
{
- type Error = Missing<WrongProtocol<ShortLifetime>>;
+ 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)
+ }
+}
- type Builder = BuilderRefValue<'value, T>;
+#[derive(thiserror::Error, Debug)]
+pub enum LifetimeIsShort<'value, 'ctx, T: ?Sized> {
+ Walking,
+ Value(&'value T),
+ Context(&'ctx T),
}
-impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Builder<'value, 'ctx, WalkerErr>
- for BuilderRefValue<'value, 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<WrongProtocol<ShortLifetime>>;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
type Value = &'value T;
@@ -141,81 +167,73 @@ impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Builder<'value, '
where
Self: Sized,
{
- Self(None)
+ Self(None, PhantomData)
}
- fn as_visitor(
+ fn as_visitor<WalkerErr: 'value>(
&mut self,
- ) -> &mut dyn crate::Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
+ ) -> &mut dyn Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
self
}
- fn finish(self) -> Result<Self::Value, crate::error::UniError<WalkerErr, Self::Error>>
+ fn finish(self) -> Result<Self::Value, Self::Error>
where
Self: Sized,
{
- self.0.ok_or(UniError::Visitor(Missing::Missing))
+ if let Some(value) = self.0 {
+ Ok(value)
+ } else {
+ Err(Missing::Missing)
+ }
}
}
-impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any>
- crate::Visitor<'value, 'ctx, WalkerErr> for BuilderRefValue<'value, T>
+impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr: 'value> Visitor<'value, 'ctx, WalkerErr>
+ for RefBuilder<'value, T, ValueLifetime>
{
- type Error = Missing<WrongProtocol<ShortLifetime>>;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn protocol(
&mut self,
- id: crate::protocol::ProtocolId,
- ) -> Option<crate::protocol::AnyVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
+ id: ProtocolId,
+ ) -> Option<AnyProtocolVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
match id {
- id if id == ProtocolId::of::<Reference<T>>() => Some(AnyVisit::new(self)),
+ id if id == ProtocolId::of::<reference::Reference<T>>() => {
+ Some(AnyVisit::new(self).erase())
+ }
_ => 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>
+impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr>
+ Visit<'value, 'ctx, reference::Reference<T>, WalkerErr>
+ for RefBuilder<'value, T, ValueLifetime>
{
- type Error = Missing<WrongProtocol<ShortLifetime>>;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn visit<'walking>(
&'walking mut self,
- accessor: <Reference<T> as crate::protocol::Protocol<'value, 'ctx>>::Accessor<
- 'walking,
- WalkerErr,
- Self::Error,
- >,
+ accessor: reference::Ref<'walking, 'value, 'ctx, T>,
) -> 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) => {
+ 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(())
}
}
}
}
-#[derive(Debug)]
-pub struct BuilderRefContext<'ctx, T: ?Sized>(Option<&'ctx T>);
-
-impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Builder<'value, 'ctx, WalkerErr>
- for BuilderRefContext<'ctx, T>
+impl<'value, 'ctx: 'value, T: ?Sized + Any> Builder<'value, 'ctx>
+ for RefBuilder<'ctx, T, ContextLifetime>
{
- type Error = Missing<WrongProtocol<ShortLifetime>>;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
type Value = &'ctx T;
@@ -223,99 +241,150 @@ impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Builder<'value, '
where
Self: Sized,
{
- Self(None)
+ Self(None, PhantomData)
}
- fn as_visitor(
+ fn as_visitor<WalkerErr: 'value>(
&mut self,
- ) -> &mut dyn crate::Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
+ ) -> &mut dyn Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> {
self
}
- fn finish(self) -> Result<Self::Value, crate::error::UniError<WalkerErr, Self::Error>>
+ fn finish(self) -> Result<Self::Value, Self::Error>
where
Self: Sized,
{
- self.0.ok_or(UniError::Visitor(Missing::Missing))
+ if let Some(value) = self.0 {
+ Ok(value)
+ } else {
+ Err(Missing::Missing)
+ }
}
}
-impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any>
- crate::Visitor<'value, 'ctx, WalkerErr> for BuilderRefContext<'ctx, T>
+impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr: 'value> Visitor<'value, 'ctx, WalkerErr>
+ for RefBuilder<'ctx, T, ContextLifetime>
{
- type Error = Missing<WrongProtocol<ShortLifetime>>;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn protocol(
&mut self,
- id: crate::protocol::ProtocolId,
- ) -> Option<crate::protocol::AnyVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
+ id: ProtocolId,
+ ) -> Option<AnyProtocolVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> {
match id {
- id if id == ProtocolId::of::<Reference<T>>() => Some(AnyVisit::new(self)),
+ id if id == ProtocolId::of::<reference::Reference<T>>() => {
+ Some(AnyVisit::new(self).erase())
+ }
_ => 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 BuilderRefContext<'ctx, T>
+impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr>
+ Visit<'value, 'ctx, reference::Reference<T>, WalkerErr>
+ for RefBuilder<'ctx, T, ContextLifetime>
{
- type Error = Missing<WrongProtocol<ShortLifetime>>;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
fn visit<'walking>(
&'walking mut self,
- accessor: <Reference<T> as crate::protocol::Protocol<'value, 'ctx>>::Accessor<
- 'walking,
- WalkerErr,
- Self::Error,
- >,
+ accessor: reference::Ref<'walking, 'value, 'ctx, T>,
) -> Result<(), UniError<WalkerErr, Self::Error>> {
- use reference::Ref::*;
-
match accessor {
- Walking(_) => Err(UniError::Visitor(Missing::Error(WrongProtocol::Error(
- ShortLifetime::Walking,
- )))),
- Value(_) => Err(UniError::Visitor(Missing::Error(WrongProtocol::Error(
- ShortLifetime::Value,
- )))),
- Context(value) | Static(value) => {
+ 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(())
}
}
}
}
-// === &mut T ===
+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;
-impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T> WalkOnce<'value, 'ctx, VisitorErr> for &'ctx mut T
-where
- T: WalkMut<'value, 'ctx, VisitorErr>,
+ 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 ErrorOnce = T::ErrorMut;
- type WalkerOnce = T::WalkerMut;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
- fn into_walker(self) -> T::WalkerMut {
- T::walker_mut(self)
+ 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, VisitorErr: 'ctx, T> WalkMut<'value, 'ctx, VisitorErr> for &'ctx mut T
-where
- T: WalkMut<'value, 'ctx, VisitorErr>,
+impl<'value, 'ctx: 'value, T: ?Sized + Any, WalkerErr>
+ Visit<'value, 'ctx, reference::Reference<T>, WalkerErr>
+ for RefBuilder<'static, T, StaticLifetime>
{
- type ErrorMut = T::ErrorMut;
- type WalkerMut = T::WalkerMut;
+ type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>;
- fn walker_mut(&'value mut self) -> T::WalkerMut {
- T::walker_mut(self)
+ 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>;
+}