Diffstat (limited to 'src/impls/core/reference.rs')
| -rw-r--r-- | src/impls/core/reference.rs | 471 |
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>; +} |