Diffstat (limited to 'src/impls/core/reference.rs')
| -rw-r--r-- | src/impls/core/reference.rs | 429 |
1 files changed, 107 insertions, 322 deletions
diff --git a/src/impls/core/reference.rs b/src/impls/core/reference.rs index 69c8f08..4016a26 100644 --- a/src/impls/core/reference.rs +++ b/src/impls/core/reference.rs @@ -1,390 +1,175 @@ -use core::{any::Any, marker::PhantomData}; +use core::any::Any; use crate::{ - build::{Build, Builder}, - error::{Missing, PrimitiveTypeError, UniError}, - protocol::{lookup_visit, AnyProtocolVisit, AnyVisit, ProtocolDescription, ProtocolId, Visit}, + protocol::{lookup_visit, VisitorMissingProtocol, WalkerMissingProtocol, lookup_hint, ProtocolId, AnyVisit, Visit}, protocols::reference, - walk::{Walk, WalkMut, WalkOnce}, - Fallible, Visitor, WalkStatus, Walker, + walk::{WalkMut, WalkOnce, Walk}, + Visitor, Walker, ControlFlow, build::{Builder, Build}, }; -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 +impl<'borrow, 'ctx, T> WalkOnce<'ctx> for &'borrow T where - T: Walk<'value, 'borrow, 'ctx>, + T: Walk<'borrow, 'ctx> { type Error = T::Error; - type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>; + type Value = T::Value; - fn into_walker<VisitorErr: 'value>(self) -> Self::Walker<VisitorErr> { - T::walker(self) + fn walk_once(self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { + T::walk(self, visitor) } } -impl<'value, 'method: 'value, 'borrow: 'method, 'ctx: 'borrow, T: ?Sized> - WalkMut<'value, 'method, 'ctx> for &'borrow T -where - T: Walk<'value, 'borrow, 'ctx>, +impl<'borrow, 'a, 'ctx, T> WalkMut<'borrow, 'ctx> for &'a T +where + T: Walk<'a, '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) + fn walk_mut(&'borrow mut self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { + T::walk(self, visitor) } } -impl<'value, 'method: 'value, 'borrow: 'method, 'ctx: 'borrow, T: ?Sized> - Walk<'value, 'method, 'ctx> for &'borrow T +impl<'borrow, 'a, 'ctx, T> Walk<'borrow, 'ctx> for &'a T where - T: Walk<'value, 'borrow, 'ctx>, + T: Walk<'a, 'ctx> { - type Error = T::Error; - - type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>; - - fn walker<VisitorErr: 'value>(&'method self) -> Self::Walker<VisitorErr> { - T::walker(self) + fn walk(&'borrow self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { + T::walk(self, visitor) } } -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<'ctx, T: ?Sized + Any> Build<'ctx> for &'ctx T { + type Builder = RefBuilder<'ctx, 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 = T::Error; - - type Walker<VisitorErr: 'value> = T::Walker<VisitorErr>; - - fn walker_mut<VisitorErr: 'value>(&'borrow mut self) -> Self::Walker<VisitorErr> { - T::walker_mut(self) - } +pub struct RefWalker<'ctx, T: ?Sized> { + value: &'ctx T, + error: Option<VisitorMissingProtocol>, } -#[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) +impl<'ctx, T: ?Sized> RefWalker<'ctx, T> { + pub fn new(value: &'ctx T) -> Self { + Self { + value, + error: None, + } } - fn as_visitor<WalkerErr: 'value>( - &mut self, - ) -> &mut dyn Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> { - self + pub fn into_error(self) -> Option<VisitorMissingProtocol> { + self.error } +} - fn finish(self) -> Result<Self::Value, Self::Error> - where - Self: Sized, - { - if let Some(value) = self.0 { - Ok(value) - } else { - Err(Missing::Missing) +impl<'ctx:, T: ?Sized + Any> Walker<'ctx> for RefWalker<'ctx, T> { + fn walk(&mut self, visitor: &mut dyn Visitor<'ctx>) -> ControlFlow { + match lookup_visit::<reference::Reference<T>, _>(visitor) { + Ok(visit) => visit.visit(reference::Ref::Context(self.value)).to_done(), + Err(err) => { + self.error = Some(err); + ControlFlow::Error + }, } } } -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>>; +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Missing value after walk.")] + MissingValue, - 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, - } - } + #[error("A value with a lifetime to short was given.")] + ShortLifetime, + + #[error(transparent)] + MissingProtocol(#[from] WalkerMissingProtocol) } -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>>; +pub struct RefBuilder<'ctx, T: ?Sized> { + value: Option<Result<&'ctx T, Error>>, +} - 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<'ctx, T: ?Sized> Default for RefBuilder<'ctx, T> { + fn default() -> Self { + Self { value: None } } } -impl<'value, 'ctx: 'value, T: ?Sized + Any> Builder<'value, 'ctx> - for RefBuilder<'ctx, T, ContextLifetime> -{ - type Error = Missing<LifetimeIsShort<'value, 'ctx, T>>; +impl<'ctx, T: ?Sized + Any> Builder<'ctx> for RefBuilder<'ctx, T> { + type Error = Error; 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> { + fn as_visitor(&mut self) -> &mut dyn Visitor<'ctx> { self } - fn finish(self) -> Result<Self::Value, Self::Error> - where - Self: Sized, - { - if let Some(value) = self.0 { - Ok(value) - } else { - Err(Missing::Missing) + fn build(self) -> Result<Self::Value, Self::Error> { + match self.value { + Some(Ok(value)) => Ok(value), + Some(Err(err)) => Err(err.into()), + None => Err(Error::MissingValue), } } } -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( +impl<'ctx, T: ?Sized + Any> Visitor<'ctx> for RefBuilder<'ctx, T> { + fn request_hint( &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, + hints: &mut dyn crate::WalkerHints<'ctx>, + _need_hint: bool, + ) -> ControlFlow { + match lookup_hint::<reference::Reference<T>, _>(hints) { + Ok(hint) => hint.hint(self, reference::Hint { + kind: Some(reference::Kind::Context), + min_len: None, + max_len: None, + }), + Err(err) => { + self.value = Some(Err(err.into())); + ControlFlow::Error + }, } } -} -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) + fn protocol(&mut self, id: crate::protocol::ProtocolId) -> Option<AnyVisit<'_, 'ctx>> { + if id == ProtocolId::of::<reference::Reference<T>>() { + Some(AnyVisit::new::<reference::Reference<T>>(self)) + } else if id == ProtocolId::of::<reference::ReferenceMut<T>>() { + Some(AnyVisit::new::<reference::ReferenceMut<T>>(self)) } else { - Err(Missing::Missing) + None } } } -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>> { +impl<'ctx, T: ?Sized + Any> Visit<'ctx, reference::Reference<T>> for RefBuilder<'ctx, T> { + fn visit(&mut self, accessor: reference::Ref<'_, 'ctx, T>) -> ControlFlow { 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), - ))), + self.value = Some(Err(Error::ShortLifetime)); + ControlFlow::Error + }, + reference::Ref::Context(value) | reference::Ref::Static(value) => { - self.0 = Some(value); - Ok(()) - } + self.value = Some(Ok(value)); + ControlFlow::Done + }, } } } -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>; +impl<'ctx, T: ?Sized + Any> Visit<'ctx, reference::ReferenceMut<T>> for RefBuilder<'ctx, T> { + fn visit(&mut self, accessor: reference::Mut<'_, 'ctx, T>) -> ControlFlow { + match accessor { + reference::Mut::Walking(_) => { + self.value = Some(Err(Error::ShortLifetime)); + ControlFlow::Error + }, + reference::Mut::Context(value) | + reference::Mut::Static(value) => { + self.value = Some(Ok(value)); + ControlFlow::Done + }, + } + } } |