34 files changed, 500 insertions, 1500 deletions
@@ -7,7 +7,7 @@ edition = "2021" serde = { version = "1.0", default-features = false, optional = true } [features] -default = ["alloc"] +default = [] std = ["alloc", "serde?/std"] alloc = ["serde?/alloc"] serde = ["dep:serde"] diff --git a/src/build.rs b/src/build.rs index 0d103ce..87c0fc8 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,5 +1,4 @@ -// pub mod builders; -// pub mod protocols; +pub mod builders; use crate::{ protocol::{SyncEffect, Visitor}, @@ -35,7 +34,7 @@ pub trait Builder<'ctx>: Default { /// Get the builder as a visitor that a walker can use. /// /// This is expected to just be `self`. - fn as_visitor(&mut self) -> &mut Visitor<'ctx>; + fn as_visitor(&mut self) -> &mut Visitor<'_, 'ctx>; /// Finish the value. /// @@ -50,12 +49,25 @@ pub enum BuildError<B, W> { Walker(W), } +#[inline] +pub fn build<'ctx, T: Build<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( + walker: W, +) -> Result<T, BuildError<<<T as Build<'ctx>>::Builder as Builder<'ctx>>::Error, W::Error>> { + let mut builder = T::Builder::default(); + + if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()).into_inner() { + return Err(BuildError::Walker(err)); + } + + builder.build().map_err(BuildError::Builder) +} + pub fn build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( walker: W, ) -> Result<B::Value, BuildError<B::Error, W::Error>> { let mut builder = B::default(); - if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { + if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()).into_inner() { return Err(BuildError::Walker(err)); } diff --git a/src/build/builders.rs b/src/build/builders.rs index 4eb1f79..5a7ca06 100644 --- a/src/build/builders.rs +++ b/src/build/builders.rs @@ -1,7 +1 @@ -mod owned; - -pub use owned::*; - -#[derive(thiserror::Error, Debug)] -#[error("The value is not complete.")] -pub struct IncompleteValue; +pub mod core; diff --git a/src/build/builders/core.rs b/src/build/builders/core.rs new file mode 100644 index 0000000..7ea094a --- /dev/null +++ b/src/build/builders/core.rs @@ -0,0 +1,2 @@ +pub mod array; +pub mod bool; diff --git a/src/build/builders/core/array.rs b/src/build/builders/core/array.rs new file mode 100644 index 0000000..2b8edb3 --- /dev/null +++ b/src/build/builders/core/array.rs @@ -0,0 +1,128 @@ +use core::{mem::MaybeUninit, ops::ControlFlow}; + +use crate::{ + any_trait, + protocol::{ + visitor::{Sequence, SequenceScope, Status}, + ControlFlowFor, Effect, Ready, + }, +}; + +#[cfg(feature = "alloc")] +use crate::protocol::AsyncEffect; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::boxed::Box; + +impl<'ctx, T, const N: usize> crate::Build<'ctx> for [T; N] +where + T: crate::Build<'ctx>, +{ + type Builder = Builder<'ctx, T::Builder, N>; +} + +#[derive(Debug)] +pub enum ArrayError<E> { + Incomplete, + Item(usize, E), +} + +pub struct Builder<'ctx, B: crate::Builder<'ctx>, const N: usize> { + array: MaybeUninit<[B::Value; N]>, + index: usize, + item_err: Option<(usize, B::Error)>, +} + +impl<'ctx, B: crate::Builder<'ctx>, const N: usize> Default for Builder<'ctx, B, N> { + fn default() -> Self { + Self { + array: MaybeUninit::uninit(), + index: 0, + item_err: None, + } + } +} + +impl<'ctx, B: crate::Builder<'ctx>, const N: usize> crate::Builder<'ctx> for Builder<'ctx, B, N> { + type Error = ArrayError<B::Error>; + + type Value = [B::Value; N]; + + fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { + self + } + + fn build(self) -> Result<Self::Value, Self::Error> { + if let Some((index, err)) = self.item_err { + return Err(ArrayError::Item(index, err)); + } + + if self.index < N { + Err(ArrayError::Incomplete) + } else { + Ok(unsafe { self.array.assume_init() }) + } + } +} + +#[cfg(not(feature = "alloc"))] +any_trait! { + impl['a, 'ctx, B: crate::Builder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ + dyn Sequence<'ctx> + 'a, + ]; +} + +#[cfg(feature = "alloc")] +any_trait! { + impl['a, 'ctx, B: crate::Builder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ + dyn Sequence<'ctx> + 'a, + dyn Sequence<'ctx, AsyncEffect> + 'a, + ]; +} + +impl<'ctx, B: crate::Builder<'ctx>, const N: usize, E: Effect> Sequence<'ctx, E> + for Builder<'ctx, B, N> +{ + #[inline] + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx, E>) -> ControlFlowFor<'a, E> { + E::wrap(async { + loop { + // Check if the array is full. + if self.index >= N { + return ControlFlow::Continue(()); + } + + // Try to build the next value. + let mut builder = B::default(); + match scope.next(builder.as_visitor()).await { + ControlFlow::Continue(Status::Done) => { + // The sequence is done so the builder wasn't given a value. + // We just throw away the empty builder. + return ControlFlow::Continue(()); + } + ControlFlow::Continue(Status::Continue) => match builder.build() { + Ok(value) => { + // Put the value in the array, and move to the next one. + unsafe { maybe_uninit_array(&mut self.array).get_unchecked_mut(self.index).write(value) }; + self.index += 1; + } + Err(err) => { + // Record the item error and return a stop signal. + self.item_err = Some((self.index, err)); + return ControlFlow::Break(()); + } + }, + ControlFlow::Break(()) => { + return ControlFlow::Break(()); + } + } + } + }) + } +} + +fn maybe_uninit_array<T, const N: usize>( + array: &mut MaybeUninit<[T; N]>, +) -> &mut [MaybeUninit<T>; N] { + unsafe { &mut *(array as *mut _ as *mut [MaybeUninit<T>; N]) } +} diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs new file mode 100644 index 0000000..dd98d0e --- /dev/null +++ b/src/build/builders/core/bool.rs @@ -0,0 +1,54 @@ +use core::ops::ControlFlow; + +use crate::{ + any::static_wrapper::OwnedStatic, + any_trait, + protocol::{visitor::Value, ControlFlowFor, Effect}, +}; + +impl<'ctx> crate::Build<'ctx> for bool { + type Builder = Builder; +} + +#[derive(Debug)] +pub enum Error { + Incomplete, +} + +pub struct Builder(Option<bool>); + +impl<'ctx> Default for Builder { + fn default() -> Self { + Self(None) + } +} + +impl<'ctx> crate::Builder<'ctx> for Builder { + type Error = Error; + + type Value = bool; + + fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { + self + } + + fn build(self) -> Result<Self::Value, Self::Error> { + self.0.ok_or(Error::Incomplete) + } +} + +any_trait! { + impl['a, 'ctx] Builder = [ + dyn Value<'a, OwnedStatic<bool>> + 'a, + ]; +} + +impl<'a, E: Effect> Value<'a, OwnedStatic<bool>, E> for Builder { + #[inline] + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, E> { + E::wrap(async move { + self.0 = Some(value); + ControlFlow::Continue(()) + }) + } +} diff --git a/src/build/builders/owned.rs b/src/build/builders/owned.rs deleted file mode 100644 index 29098c8..0000000 --- a/src/build/builders/owned.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::{build::protocols, implementer, protocol::ImplementerExt, walk, Builder}; - -use super::IncompleteValue; - -pub struct OwnedBuilder<T> { - value: Option<T>, -} - -impl<T> Default for OwnedBuilder<T> { - fn default() -> Self { - Self { value: None } - } -} - -impl<'ctx, T: 'static> Builder<'ctx> for OwnedBuilder<T> { - type Error = IncompleteValue; - - type Value = T; - - fn as_visitor(&mut self) -> &mut dyn crate::protocol::Implementer<'ctx> { - self - } - - fn build(self) -> Result<Self::Value, Self::Error> { - self.value.ok_or(IncompleteValue) - } -} - -implementer! { - impl['ctx, T: 'static] OwnedBuilder<T> = [ - protocols::owned::Owned<T>, - protocols::hint::RequestHint, - ]; -} - -impl<'ctx, T: 'static> protocols::hint::RequestHintObject<'ctx> for OwnedBuilder<T> { - fn request_hint( - &mut self, - hints: &mut dyn crate::protocol::Implementer<'ctx>, - ) -> Result<(), ()> { - if let Some(interface) = - hints.interface_for::<walk::protocols::hint::Hint<protocols::owned::Owned<T>>>() - { - interface.as_object().hint(self, ()) - } else { - Ok(()) - } - } -} - -impl<'ctx, T: 'static> protocols::owned::Object<'ctx, T> for OwnedBuilder<T> { - fn visit(&mut self, value: T) -> Result<(), ()> { - self.value = Some(value); - Ok(()) - } -} diff --git a/src/build/protocols.rs b/src/build/protocols.rs deleted file mode 100644 index fbd4fc0..0000000 --- a/src/build/protocols.rs +++ /dev/null @@ -1,195 +0,0 @@ -pub mod hint { -} - -pub mod recoverable { - use crate::{ - protocol::{Implementer, Protocol}, - walk::protocols::hint::Meta, - }; - - /// Protocol for providing a recoverable walker. - /// - /// This protocol is implemented by visitors. - pub enum Recoverable {} - - /// Implemented by walkers that can be reset. - pub trait RecoverableWalker<'ctx> { - /// Start a new walk with the walker reset to it's starting state. - fn new_walk(&mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<(), ()>; - } - - /// Object implementing the [`Recoverable`] protocol. - pub trait Object<'ctx> { - /// Visit with a recoverable walker. - /// - /// The visitor can then use the `walker` to try multiple different ways - /// of walking. - fn visit(&mut self, walker: &mut dyn RecoverableWalker<'ctx>) -> Result<(), ()>; - } - - impl Protocol for Recoverable { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx>; - } - - impl Meta for Recoverable { - type Known<'a, 'ctx: 'a> = (); - - type Hint<'a, 'ctx: 'a> = (); - } -} - -pub mod owned { - use core::marker::PhantomData; - - use crate::{protocol::Protocol, walk::protocols::hint::Meta}; - - pub struct Owned<T: 'static>(PhantomData<fn() -> T>); - - pub trait Object<'ctx, T: 'static> { - fn visit(&mut self, value: T) -> Result<(), ()>; - } - - impl<T: 'static> Protocol for Owned<T> { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx, T>; - } - - impl<T: 'static> Meta for Owned<T> { - type Known<'a, 'ctx: 'a> = (); - - type Hint<'a, 'ctx: 'a> = (); - } -} - -pub mod borrowed { -} - -pub mod borrowed_mut { - use core::marker::PhantomData; - - use crate::{protocol::Protocol, walk::protocols::hint::Meta}; - - pub struct BorrowedMut<T: 'static>(PhantomData<fn() -> T>); - - pub enum Value<'a, 'ctx, T: 'static> { - Temp(&'a mut T), - Context(&'ctx mut T), - Static(&'static mut T), - } - - pub trait Object<'ctx, T: 'static> { - fn visit(&mut self, value: Value<'_, 'ctx, T>) -> Result<(), ()>; - } - - impl<T: 'static> Protocol for BorrowedMut<T> { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx, T>; - } - - pub enum Kind { - Temp, - Context, - Static, - } - - pub struct Known { - pub kind: Option<Kind>, - } - - pub struct Hint { - pub kind: Option<Kind>, - } - - impl<T: 'static> Meta for BorrowedMut<T> { - type Known<'a, 'ctx: 'a> = Known; - - type Hint<'a, 'ctx: 'a> = Hint; - } -} - -pub mod tagged { -} - -pub mod sequence { - use crate::{ - protocol::{Implementer, Protocol}, - walk::protocols::hint::Meta, - }; - - pub enum Sequence {} - - #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] - pub enum Status { - Done, - Continue, - } - - pub trait SequenceWalker<'ctx> { - fn next(&mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<Status, ()>; - } - - pub trait Object<'ctx> { - fn visit(&mut self, walker: &mut dyn SequenceWalker<'ctx>) -> Result<(), ()>; - } - - impl Protocol for Sequence { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx>; - } - - #[derive(Default)] - pub struct Known { - pub len: (usize, Option<usize>), - } - - pub struct Hint { - pub len: (usize, Option<usize>), - } - - impl Meta for Sequence { - type Known<'a, 'ctx: 'a> = Known; - - type Hint<'a, 'ctx: 'a> = Hint; - } -} - -pub mod map { - use crate::{ - protocol::{Implementer, Protocol}, - walk::protocols::hint::Meta, - }; - - pub enum Map {} - - #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] - pub enum Status { - Done, - Continue, - } - - pub trait MapWalker<'ctx> { - fn next_key(&mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<Status, ()>; - - fn value(&mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<(), ()>; - } - - pub trait Object<'ctx> { - fn visit(&mut self, walker: &mut dyn MapWalker<'ctx>) -> Result<(), ()>; - } - - impl Protocol for Map { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx>; - } - - #[derive(Default)] - pub struct Known { - pub len: (usize, Option<usize>), - } - - pub struct Hint { - pub len: (usize, Option<usize>), - } - - impl Meta for Map { - type Known<'a, 'ctx: 'a> = Known; - - type Hint<'a, 'ctx: 'a> = Hint; - } -} diff --git a/src/impls/alloc.rs b/src/impls/alloc.rs deleted file mode 100644 index 67c81e2..0000000 --- a/src/impls/alloc.rs +++ /dev/null @@ -1 +0,0 @@ -// mod string; diff --git a/src/impls/alloc/string.rs b/src/impls/alloc/string.rs deleted file mode 100644 index 118eec0..0000000 --- a/src/impls/alloc/string.rs +++ /dev/null @@ -1,213 +0,0 @@ -use core::marker::PhantomData; - -use ::alloc::string::String; - -use crate::{error::{BasicError, UniError}, WalkerHints, protocol::{ProtocolId, AnyHint, Hint, lookup_visit, lookup_hint, AnyVisit, Protocol}, protocols::{str::Str, self}, HintGiven, walk::{WalkOnce, WalkMut, Walk}, build::{Builder, Build}}; - -macro_rules! impl_walker { - ($walker:ident) => { - impl<'value, 'ctx: 'value, VisitorErr: 'ctx> crate::Walker<'value, 'ctx, VisitorErr> - for $walker<'value, 'ctx> - { - type Error = BasicError; - - fn hints(&mut self) -> &mut dyn WalkerHints<'value, 'ctx, VisitorErr, Error = Self::Error> { - self - } - } - } -} - -macro_rules! impl_hints { - ($walker:ident, [$($protocol:ty),* $(,)?]) => { - impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkerHints<'value, 'ctx, VisitorErr> - for $walker<'value, 'ctx> - { - type Error = BasicError; - - fn protocol( - &mut self, - id: ProtocolId, - ) -> Option<AnyHint<'_, 'value, 'ctx, Self::Error, VisitorErr>> { - match id { - $(id if id == ProtocolId::of::<$protocol>() => Some(AnyHint::new(self)),)? - _ => None, - } - } - } - } -} - -pub struct WalkerOnce<'value, 'ctx: 'value>(String, PhantomData<&'value ()>); - -impl_walker!(WalkerOnce); - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkerHints<'value, 'ctx, VisitorErr> - for WalkerOnce<'value, 'ctx> -{ - type Error = BasicError; - - fn protocol( - &mut self, - id: ProtocolId, - ) -> Option<AnyHint<'_, 'value, 'ctx, Self::Error, VisitorErr>> { - match id { - id if id == ProtocolId::of::<Str>() => Some(AnyHint::new(self)), - _ => None, - } - } -} - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Hint<'value, 'ctx, Str, VisitorErr> - for Walker<'value, 'ctx> -{ - type Error = BasicError; - - fn hint( - &mut self, - visitor: &mut dyn crate::Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>, - _hint: <Str as crate::protocol::Protocol<'value, 'ctx>>::Hint, - ) -> Result<HintGiven, UniError<Self::Error, VisitorErr>> { - lookup_visit::<Str, _, _>(visitor) - .map_err(UniError::Walker)? - .ok_or_else(|| UniError::Walker(BasicError("visitor is missing the str protocol")))? - .visit(protocols::str::Data::Value(self.0))?; - - Ok(HintGiven) - } - - fn known( - &mut self, - _hint: &<Str as crate::protocol::Protocol<'value, 'ctx>>::Hint, - ) -> Result<<Str as crate::protocol::Protocol<'value, 'ctx>>::Known, BasicError> { - Ok(protocols::str::Known { - len: Some(self.0.len()), - kind: Some(protocols::str::Kind::Value), - }) - } -} - -pub struct WalkerMut<'value, 'ctx: 'value>(&'value mut String, PhantomData<&'ctx ()>); -pub struct WalkerRef<'value, 'ctx: 'value>(&'value String, PhantomData<&'ctx ()>); - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkOnce<'value, 'ctx, VisitorErr> for &'ctx str { - type Error = BasicError; - type Walker = Walker<'value, 'ctx>; - - fn into_walker(self) -> Self::Walker { - Walker(self, PhantomData) - } -} - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkMut<'value, 'ctx, VisitorErr> for &'ctx str { - type ErrorMut = BasicError; - type WalkerMut = Walker<'value, 'ctx>; - - fn walker_mut(&'value mut self) -> Self::Walker { - Walker(self, PhantomData) - } -} - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Walk<'value, 'ctx, VisitorErr> for &'ctx str { - type ErrorRef = BasicError; - type WalkerRef = Walker<'value, 'ctx>; - - fn walker_ref(&'value self) -> Self::Walker { - Walker(self, PhantomData) - } -} - -pub struct Visitor<'value>(Option<&'value str>); - -impl<'value, 'ctx: 'value, WalkerErr: 'value> crate::Visitor<'value, 'ctx, WalkerErr> - for Visitor<'value> -{ - type Error = BasicError; - - fn request_hint( - &mut self, - hints: &mut dyn WalkerHints<'value, 'ctx, BasicError, Error = WalkerErr>, - ) -> Result<Option<HintGiven>, UniError<WalkerErr, BasicError>> { - if let Some(hint) = lookup_hint::<Str, _, _>(hints).map_err(UniError::Visitor)? { - Ok(Some(hint.hint( - self, - protocols::str::Hint { - kind: Some(protocols::str::Kind::Value), - min_len: None, - max_len: None, - }, - )?)) - } else { - Ok(None) - } - } - - fn protocol( - &mut self, - id: ProtocolId, - ) -> Option<AnyVisit<'_, 'value, 'ctx, WalkerErr, BasicError>> { - match id { - id if id == ProtocolId::of::<Str>() => Some(AnyVisit::new(self)), - _ => None, - } - } -} - -impl<'value, 'ctx: 'value, WalkerErr: 'value> crate::Visit<'value, 'ctx, Str, WalkerErr> - for Visitor<'value> -{ - type Error = BasicError; - - fn visit<'walking>( - &'walking mut self, - accessor: <Str as Protocol<'value, 'ctx>>::Accessor<'walking, WalkerErr, BasicError>, - ) -> Result<(), UniError<WalkerErr, BasicError>> { - match accessor { - protocols::str::Data::Value(str) - | protocols::str::Data::Context(str) - | protocols::str::Data::Static(str) => self.0 = Some(str), - protocols::str::Data::Walking(_) => { - return Err(UniError::Visitor(BasicError( - "str doesn't live long enough", - ))) - } - } - Ok(()) - } -} - -impl<'value, 'ctx: 'value, WalkerErr: 'value> Builder<'value, 'ctx, WalkerErr> for Visitor<'value> { - type Error = BasicError; - - type Value = &'value str; - - fn init() -> Self - where - Self: Sized, - { - Visitor(None) - } - - fn as_visitor( - &mut self, - ) -> &mut dyn crate::Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> { - self - } - - fn finish(self) -> Result<Self::Value, UniError<WalkerErr, Self::Error>> - where - Self: Sized, - { - if let Some(str) = self.0 { - Ok(str) - } else { - Err(UniError::Visitor(BasicError("missing str"))) - } - } -} - -impl<'value, 'ctx: 'value, WalkerErr: 'value> Build<'value, 'ctx, WalkerErr> for &'value str { - type Error = BasicError; - - type Builder = Visitor<'value>; -} diff --git a/src/impls/core.rs b/src/impls/core.rs deleted file mode 100644 index 162635e..0000000 --- a/src/impls/core.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod bool; -// pub mod iterator; -// pub mod reference; -// pub mod reference_mut; -// pub mod str; diff --git a/src/impls/core/bool.rs b/src/impls/core/bool.rs deleted file mode 100644 index e1460ee..0000000 --- a/src/impls/core/bool.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::{ - build::{builders::OwnedBuilder, Build}, - walk::walkers::OwnedCloneWalker, - Walk, -}; - -#[derive(thiserror::Error, Debug)] -#[error("The value is complete.")] -pub struct IncompleteValue; - -impl<'ctx> Walk<'ctx> for bool { - type Walker = OwnedCloneWalker<Self>; -} - -impl<'ctx> Build<'ctx> for bool { - type Builder = OwnedBuilder<Self>; -} diff --git a/src/impls/core/iterator.rs b/src/impls/core/iterator.rs deleted file mode 100644 index cdcd71b..0000000 --- a/src/impls/core/iterator.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::protocol::ImplementerExt; -use crate::protocols::{sequence, ControlFlow}; -use crate::walk::WalkOnce; - -pub struct IterWalker<'ctx, I> -where - I: Iterator, - <I as Iterator>::Item: WalkOnce<'ctx>, -{ - iter: I, - err: Option<<<I as Iterator>::Item as WalkOnce<'ctx>>::Error>, -} - -impl<'ctx, I> IterWalker<'ctx, I> -where - I: Iterator, - <I as Iterator>::Item: WalkOnce<'ctx>, -{ - pub fn new<T: IntoIterator<IntoIter = I>>(iter: T) -> Self { - Self { - iter: iter.into_iter(), - err: None, - } - } -} - -impl<'ctx, I> WalkOnce<'ctx> for IterWalker<'ctx, I> -where - I: Iterator, - <I as Iterator>::Item: WalkOnce<'ctx>, -{ - type Error = <<I as Iterator>::Item as WalkOnce<'ctx>>::Error; - - type Value = (); - - #[inline] - fn walk_once( - mut self, - visitor: &mut dyn crate::protocol::Implementer<'ctx>, - ) -> Result<Self::Value, Self::Error> { - if let Some(interface) = visitor.interface_for::<sequence::Sequence>() { - match interface.as_object().visit(&mut self) { - ControlFlow::Done => Ok(()), - ControlFlow::Error => match self.err { - Some(err) => Err(err), - None => Ok(()), - }, - } - } else { - Ok(()) - } - } -} - -impl<'ctx, I> sequence::Accessor<'ctx> for IterWalker<'ctx, I> -where - I: Iterator, - <I as Iterator>::Item: WalkOnce<'ctx>, -{ - fn next( - &mut self, - visitor: &mut dyn crate::protocol::Implementer<'ctx>, - ) -> sequence::ControlFlow { - if let Some(item) = self.iter.next() { - match item.walk_once(visitor) { - Ok(_) => sequence::ControlFlow::Continue, - Err(err) => { - self.err = Some(err); - sequence::ControlFlow::Error - } - } - } else { - sequence::ControlFlow::Done - } - } -} diff --git a/src/impls/core/reference.rs b/src/impls/core/reference.rs deleted file mode 100644 index 0f5038d..0000000 --- a/src/impls/core/reference.rs +++ /dev/null @@ -1,244 +0,0 @@ -use core::any::Any; - -use crate::{ - build::{Build, Builder}, - protocol::{ - lookup_hint, lookup_visit, AnyHint, AnyVisit, Hint, ProtocolId, Visit, - VisitorMissingProtocol, WalkerMissingProtocol, - }, - protocols::{recoverable, reference}, - walk::{Walk, WalkMut, WalkOnce}, - ControlFlow, Visitor, Walker, -}; - -impl<'borrow, 'ctx, T> WalkOnce<'ctx> for &'borrow T -where - T: Walk<'borrow, 'ctx>, -{ - type Error = T::Error; - - type Value = T::Value; - - fn walk_once(self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - T::walk(self, visitor) - } -} - -impl<'borrow, 'a, 'ctx, T> WalkMut<'borrow, 'ctx> for &'a T -where - T: Walk<'a, 'ctx>, -{ - fn walk_mut( - &'borrow mut self, - visitor: &mut dyn Visitor<'ctx>, - ) -> Result<Self::Value, Self::Error> { - T::walk(self, visitor) - } -} - -impl<'borrow, 'a, 'ctx, T> Walk<'borrow, 'ctx> for &'a T -where - T: Walk<'a, 'ctx>, -{ - fn walk(&'borrow self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - T::walk(self, visitor) - } -} - -impl<'ctx, T: ?Sized + Any> Build<'ctx> for &'ctx T { - type Builder = RefBuilder<'ctx, T>; -} - -pub struct RefWalker<'ctx, T: ?Sized> { - value: &'ctx T, - error: Option<VisitorMissingProtocol>, -} - -impl<'ctx, T: ?Sized> RefWalker<'ctx, T> { - pub fn new(value: &'ctx T) -> Self { - Self { value, error: None } - } -} - -impl<'ctx, T: ?Sized + Any> WalkOnce<'ctx> for RefWalker<'ctx, T> { - type Error = VisitorMissingProtocol; - - type Value = (); - - fn walk_once(mut self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - match visitor.request_hint(&mut self, false) { - ControlFlow::Continue => { - Hint::<reference::Reference<T>>::hint( - &mut self, - visitor, - reference::Hint { - kind: None, - min_len: None, - max_len: None, - }, - ); - } - _ => {} - } - - if let Some(err) = self.error { - Err(err) - } else { - Ok(()) - } - } -} - -impl<'ctx, T: ?Sized + Any> Walker<'ctx> for RefWalker<'ctx, T> { - fn protocol(&mut self, id: ProtocolId) -> Option<crate::protocol::AnyHint<'_, 'ctx>> { - if id == ProtocolId::of::<reference::Reference<T>>() { - Some(AnyHint::new::<reference::Reference<T>>(self)) - } else if id == ProtocolId::of::<reference::Reference<T>>() { - Some(AnyHint::new::<recoverable::Recoverable>(self)) - } else { - None - } - } -} - -impl<'ctx, T: ?Sized + Any> Hint<'ctx, reference::Reference<T>> for RefWalker<'ctx, T> { - fn hint(&mut self, visitor: &mut dyn Visitor<'ctx>, _hint: reference::Hint) -> 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 - } - } - } - - fn known(&mut self, _hint: &reference::Hint) -> reference::Known { - reference::Known { - kind: Some(reference::Kind::Context), - len: None, - } - } -} - -impl<'ctx, T: ?Sized + Any> Hint<'ctx, recoverable::Recoverable> for RefWalker<'ctx, T> { - fn hint(&mut self, visitor: &mut dyn Visitor<'ctx>, _hint: ()) -> ControlFlow { - match lookup_visit::<recoverable::Recoverable, _>(visitor) { - Ok(visit) => visit.visit(self).to_done(), - Err(err) => { - self.error = Some(err); - ControlFlow::Error - } - } - } - - fn known(&mut self, _hint: &()) {} -} - -impl<'ctx, T: ?Sized + Any> recoverable::Accessor<'ctx> for RefWalker<'ctx, T> { - fn new_walk(&mut self, visitor: &mut dyn Visitor<'ctx>) -> ControlFlow { - todo!() - } -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Missing value after walk.")] - MissingValue, - - #[error("A value with a lifetime to short was given.")] - ShortLifetime, - - #[error(transparent)] - MissingProtocol(#[from] WalkerMissingProtocol), -} - -pub struct RefBuilder<'ctx, T: ?Sized> { - value: Option<Result<&'ctx T, Error>>, -} - -impl<'ctx, T: ?Sized> Default for RefBuilder<'ctx, T> { - fn default() -> Self { - Self { value: None } - } -} - -impl<'ctx, T: ?Sized + Any> Builder<'ctx> for RefBuilder<'ctx, T> { - type Error = Error; - - type Value = &'ctx T; - - fn as_visitor(&mut self) -> &mut dyn Visitor<'ctx> { - self - } - - 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<'ctx, T: ?Sized + Any> Visitor<'ctx> for RefBuilder<'ctx, T> { - fn request_hint( - &mut self, - hints: &mut dyn crate::Walker<'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 - } - } - } - - 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 { - None - } - } -} - -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(_) => { - self.value = Some(Err(Error::ShortLifetime)); - ControlFlow::Error - } - reference::Ref::Context(value) | reference::Ref::Static(value) => { - self.value = Some(Ok(value)); - ControlFlow::Done - } - } - } -} - -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 - } - } - } -} diff --git a/src/impls/core/reference_mut.rs b/src/impls/core/reference_mut.rs deleted file mode 100644 index 98427fe..0000000 --- a/src/impls/core/reference_mut.rs +++ /dev/null @@ -1,162 +0,0 @@ -use core::any::Any; - -use crate::{ - build::{Build, Builder}, - protocol::{ - lookup_hint, lookup_visit, AnyVisit, ProtocolId, Visit, VisitorMissingProtocol, - WalkerMissingProtocol, - }, - protocols::reference, - walk::{Walk, WalkMut, WalkOnce}, - ControlFlow, Visitor, Walker, -}; - -impl<'borrow, 'ctx, T> WalkOnce<'ctx> for &'borrow mut T -where - T: WalkMut<'borrow, 'ctx>, -{ - type Error = T::Error; - - type Value = T::Value; - - fn walk_once(self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - T::walk_mut(self, visitor) - } -} - -impl<'borrow, 'ctx, T> WalkMut<'borrow, 'ctx> for &'borrow mut T -where - T: WalkMut<'borrow, 'ctx>, -{ - fn walk_mut( - &'borrow mut self, - visitor: &mut dyn Visitor<'ctx>, - ) -> Result<Self::Value, Self::Error> { - T::walk_mut(self, visitor) - } -} - -impl<'borrow, 'ctx, T> Walk<'borrow, 'ctx> for &'borrow mut T -where - T: Walk<'borrow, 'ctx>, -{ - fn walk(&'borrow self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - T::walk(self, visitor) - } -} - -impl<'ctx, T: ?Sized + Any> Build<'ctx> for &'ctx mut T { - type Builder = MutBuilder<'ctx, T>; -} - -pub struct MutWalker<'ctx, T: ?Sized> { - value: Option<&'ctx mut T>, -} - -impl<'ctx, T: ?Sized> MutWalker<'ctx, T> { - pub fn new(value: &'ctx mut T) -> Self { - Self { - value: Some(value), - } - } -} - -impl<'ctx, T: ?Sized + Any> WalkOnce<'ctx> for MutWalker<'ctx, T> { - type Error = VisitorMissingProtocol; - - type Value = (); - - fn walk_once(mut self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - if let Some(value) = self.value.take() { - let visit = lookup_visit::<reference::ReferenceMut<T>, _>(visitor)?; - visit.visit(reference::Mut::Context(value)); - } - Ok(()) - } -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Missing value after walk.")] - MissingValue, - - #[error("A value with a lifetime to short was given.")] - ShortLifetime, - - #[error(transparent)] - MissingProtocol(#[from] WalkerMissingProtocol), -} - -pub struct MutBuilder<'ctx, T: ?Sized> { - value: Option<Result<&'ctx mut T, Error>>, -} - -impl<'ctx, T: ?Sized> Default for MutBuilder<'ctx, T> { - fn default() -> Self { - Self { value: None } - } -} - -impl<'ctx, T: ?Sized + Any> Builder<'ctx> for MutBuilder<'ctx, T> { - type Error = Error; - - type Value = &'ctx mut T; - - fn as_visitor(&mut self) -> &mut dyn Visitor<'ctx> { - self - } - - 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<'ctx, T: ?Sized + Any> Visitor<'ctx> for MutBuilder<'ctx, T> { - fn request_hint( - &mut self, - hints: &mut dyn crate::Walker<'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 - } - } - } - - fn protocol(&mut self, id: crate::protocol::ProtocolId) -> Option<AnyVisit<'_, 'ctx>> { - if id == ProtocolId::of::<reference::ReferenceMut<T>>() { - Some(AnyVisit::new(self)) - } else { - None - } - } -} - -impl<'ctx, T: ?Sized + Any> Visit<'ctx, reference::ReferenceMut<T>> for MutBuilder<'ctx, T> { - fn visit(&mut self, accessor: reference::Mut<'_, 'ctx, T>) -> ControlFlow { - match accessor { - reference::Mut::Walking(_) => { - self.value = Some(Err(Error::ShortLifetime)); - ControlFlow::Continue - } - reference::Mut::Context(value) | reference::Mut::Static(value) => { - self.value = Some(Ok(value)); - ControlFlow::Done - } - } - } -} diff --git a/src/impls/core/str.rs b/src/impls/core/str.rs deleted file mode 100644 index 0ff2de8..0000000 --- a/src/impls/core/str.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::{ - protocol::VisitorMissingProtocol, - walk::{Walk, WalkMut, WalkOnce}, - Visitor, Walker, -}; - -use super::{reference::RefWalker, reference_mut::MutWalker}; - -impl<'ctx> WalkOnce<'ctx> for &'ctx str { - type Error = VisitorMissingProtocol; - - type Value = (); - - #[inline] - fn walk_once(self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - self.walk(visitor) - } -} - -impl<'borrow, 'ctx> WalkMut<'borrow, 'ctx> for &'ctx str { - #[inline] - fn walk_mut( - &'borrow mut self, - visitor: &mut dyn Visitor<'ctx>, - ) -> Result<Self::Value, Self::Error> { - self.walk(visitor) - } -} - -impl<'borrow, 'ctx> Walk<'borrow, 'ctx> for &'ctx str { - #[inline] - fn walk(&'borrow self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - RefWalker::new(*self).walk_once(visitor) - } -} - -impl<'ctx> WalkOnce<'ctx> for &'ctx mut str { - type Error = VisitorMissingProtocol; - - type Value = (); - - #[inline] - fn walk_once(self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - MutWalker::new(self).walk_once(visitor) - } -} - -impl<'ctx> WalkMut<'ctx, 'ctx> for &'ctx mut str { - #[inline] - fn walk_mut( - &'ctx mut self, - visitor: &mut dyn Visitor<'ctx>, - ) -> Result<Self::Value, Self::Error> { - MutWalker::new(*self).walk_once(visitor) - } -} - -impl<'ctx> Walk<'ctx, 'ctx> for &'ctx mut str { - #[inline] - fn walk(&'ctx self, visitor: &mut dyn Visitor<'ctx>) -> Result<Self::Value, Self::Error> { - RefWalker::new(*self).walk_once(visitor) - } -} @@ -9,7 +9,6 @@ extern crate alloc; pub mod any; mod build; -// pub mod builtins; pub mod protocol; pub mod symbol; mod walk; diff --git a/src/protocol.rs b/src/protocol.rs index 26ec664..37bcee7 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -33,26 +33,58 @@ //! This is done via the help of the [`AnyImpl`] type. This is not required for the core //! idea of DIDETs. +use core::{ + future::Future, + pin::{pin, Pin}, + ptr, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, +}; + use crate::any::AnyTrait; pub mod visitor; pub mod walker; -#[cfg(not(feature = "std"))] +#[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -pub type Visitor<'ctx> = dyn AnyTrait<'ctx>; -pub type Walker<'ctx> = dyn AnyTrait<'ctx>; +pub type Visitor<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a; +pub type Walker<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a; + +pub trait Effect: 'static { + type ControlFlow<'a, C, B>: Future<Output = core::ops::ControlFlow<B, C>>; -pub trait Effect { - type ControlFlow<'a, C, B>; + fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( + future: F, + ) -> Self::ControlFlow<'a, C, B>; } + pub type ControlFlowFor<'a, E = SyncEffect, C = (), B = ()> = <E as Effect>::ControlFlow<'a, C, B>; pub enum SyncEffect {} impl Effect for SyncEffect { - type ControlFlow<'a, C, B> = core::ops::ControlFlow<B, C>; + type ControlFlow<'a, C, B> = Ready<core::ops::ControlFlow<B, C>>; + + fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( + future: F, + ) -> Self::ControlFlow<'a, C, B> { + let pinned_future = pin!(future); + + let waker = noop(); + let mut cx = Context::<'_>::from_waker(&waker); + match pinned_future.poll(&mut cx) { + Poll::Ready(value) => Ready::new(value), + Poll::Pending => panic!("expected future to be ready"), + } + } +} + +fn noop() -> Waker { + const VTABLE: RawWakerVTable = RawWakerVTable::new(|_| RAW, |_| {}, |_| {}, |_| {}); + const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); + + unsafe { Waker::from_raw(RAW) } } #[cfg(feature = "alloc")] @@ -62,4 +94,38 @@ pub enum AsyncEffect {} impl Effect for AsyncEffect { type ControlFlow<'a, C, B> = core::pin::Pin<Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + 'a>>; + + fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( + future: F, + ) -> Self::ControlFlow<'a, C, B> { + Box::pin(future) + } +} + +#[must_use] +pub struct Ready<T>(Option<T>); + +impl<T> Unpin for Ready<T> {} + +impl<T> Future for Ready<T> { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> { + unsafe { + Poll::Ready(self.0.take().unwrap_unchecked()) + } + } +} + +impl<T> Ready<T> { + pub fn new(value: T) -> Self { + Self(Some(value)) + } + + #[must_use] + pub fn into_inner(self) -> T { + unsafe { self.0.unwrap_unchecked() } + // .expect("Called `into_inner()` on `Ready` after completion") + } } diff --git a/src/protocol/visitor/borrow.rs b/src/protocol/visitor/borrow.rs deleted file mode 100644 index 511d429..0000000 --- a/src/protocol/visitor/borrow.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! Protocol for giving a visitor a borrowed value. - -use core::marker::PhantomData; - -use crate::{builtins::walker::hint::Meta, protocol::Protocol}; - -pub struct Value<T: ?Sized>(PhantomData<fn() -> *const T>); - -pub enum Kind<'a, 'ctx: 'a, T: ?Sized> { - Temp(&'a T), - Context(&'ctx T), - TempMut(&'a mut T), - ContextMut(&'ctx mut T), -} - -impl<'a, 'ctx, T: ?Sized> Kind<'a, 'ctx, T> { - pub fn into_temp(self) -> &'a T { - use Kind as K; - match self { - K::Temp(v) | K::Context(v) => v, - K::TempMut(v) | K::ContextMut(v) => v, - } - } - - pub fn into_context(self) -> Result<&'ctx T, Self> { - use Kind as K; - match self { - K::Context(v) => Ok(v), - K::ContextMut(v) => Ok(v), - this @ (K::Temp(_) | K::TempMut(_)) => Err(this), - } - } - - pub fn into_temp_mut(self) -> Result<&'a mut T, Self> { - use Kind as K; - match self { - K::TempMut(v) | K::ContextMut(v) => Ok(v), - this @ (K::Temp(_) | K::Context(_)) => Err(this), - } - } - - pub fn into_context_mut(self) -> Result<&'ctx mut T, Self> { - use Kind as K; - match self { - K::ContextMut(v) => Ok(v), - this @ (K::Temp(_) | K::Context(_) | K::TempMut(_)) => { - Err(this) - } - } - } - - pub fn variant(&self) -> KindVariants { - use Kind as K; - use KindVariants as V; - match self { - K::Temp(_) => V::Temp, - K::Context(_) => V::Context, - K::TempMut(_) => V::TempMut, - K::ContextMut(_) => V::ContextMut, - } - } -} - -pub trait Object<'ctx, T: 'static> { - fn visit(&mut self, value: Kind<'_, 'ctx, T>) -> Result<(), ()>; -} - -impl<T: 'static> Protocol for Value<T> { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx, T>; -} - -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] -pub enum KindVariants { - Temp, - Context, - TempMut, - ContextMut, -} - -impl KindVariants { - pub fn can_become(&self, wanted: Self) -> bool { - use KindVariants as V; - match (self, wanted) { - (V::Temp, V::Temp) => true, - (V::Temp, V::Context) => false, - (V::Temp, V::TempMut) => false, - (V::Temp, V::ContextMut) => false, - (V::Context, V::Temp) => true, - (V::Context, V::Context) => true, - (V::Context, V::TempMut) => false, - (V::Context, V::ContextMut) => false, - (V::TempMut, V::Temp) => true, - (V::TempMut, V::Context) => false, - (V::TempMut, V::TempMut) => true, - (V::TempMut, V::ContextMut) => false, - (V::ContextMut, V::Temp) => true, - (V::ContextMut, V::Context) => true, - (V::ContextMut, V::TempMut) => true, - (V::ContextMut, V::ContextMut) => true, - } - } -} - -pub struct Known { - pub kind: Option<KindVariants>, -} - -pub struct Hint { - pub kind: Option<KindVariants>, -} - -impl<T: 'static> Meta for Value<T> { - type Known<'a, 'ctx: 'a> = Known; - - type Hint<'a, 'ctx: 'a> = Hint; -} diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index 87c073d..d012b73 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -9,7 +9,7 @@ pub trait RequestHint<'ctx, E: Effect = SyncEffect> { /// /// `walker` is what the visitor (`self`) will call to give a hint using the /// [`Hint`][crate::builtins::walker::Hint] protocol. - fn request_hint<'a>(&'a mut self, walker: &'a mut Walker<'ctx>) -> ControlFlowFor<'a, E>; + fn request_hint<'a>(&'a mut self, walker: &'a mut Walker<'a, 'ctx>) -> ControlFlowFor<'a, E>; } nameable! { diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index 9b24377..44a80c6 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -22,7 +22,7 @@ nameable! { } pub trait SequenceScope<'ctx, E: Effect = SyncEffect> { - fn next<'a>(&'a mut self, visitor: &'a mut Visitor<'ctx>) -> ControlFlowFor<'a, E, Status>; + fn next<'a>(&'a mut self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, E, Status>; } #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] diff --git a/src/protocol/visitor/tagged.rs b/src/protocol/visitor/tagged.rs index 4cf3912..e6ff575 100644 --- a/src/protocol/visitor/tagged.rs +++ b/src/protocol/visitor/tagged.rs @@ -25,9 +25,9 @@ nameable! { pub trait TaggedScope<'ctx, E: Effect = SyncEffect> { fn kind(&mut self) -> Symbol; - fn tag<'a>(&'a mut self, visitor: &'a mut Visitor<'ctx>) -> ControlFlowFor<'a, E>; + fn tag<'a>(&'a mut self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, E>; - fn value<'a>(&'a mut self, visitor: &'a mut Visitor<'ctx>) -> ControlFlowFor<'a, E>; + fn value<'a>(&'a mut self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, E>; } pub struct Known { diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index ed8a8ec..d8461f5 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -55,7 +55,6 @@ mod test { AnyTrait, }, any_trait, - protocol::SyncControlFlow, }; use super::*; @@ -64,7 +63,7 @@ mod test { fn visit() { struct Visitor(Option<i32>); - impl Value<'_, OwnedStatic<i32>, SyncControlFlow> for Visitor { + impl Value<'_, OwnedStatic<i32>> for Visitor { fn visit( &mut self, OwnedStatic(value): OwnedStatic<i32>, @@ -74,7 +73,7 @@ mod test { } } - impl Value<'_, BorrowedStatic<'_, i32>, SyncControlFlow> for Visitor { + impl Value<'_, BorrowedStatic<'_, i32>> for Visitor { fn visit( &mut self, BorrowedStatic(value): BorrowedStatic<'_, i32>, @@ -86,15 +85,15 @@ mod test { any_trait! { impl['a, 'ctx] Visitor = [ - dyn Value<'a, OwnedStatic<i32>, SyncControlFlow> + 'a, - dyn Value<'a, BorrowedStatic<'ctx, i32, SyncControlFlow>> + 'a, + dyn Value<'a, OwnedStatic<i32>> + 'a, + dyn Value<'a, BorrowedStatic<'ctx, i32>> + 'a, ]; } let mut v = Visitor(None); let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<'_, OwnedStatic<i32, SyncControlFlow>>>() + .upcast_mut::<dyn Value<'_, OwnedStatic<i32>>>() .unwrap() .visit(OwnedStatic(42)); @@ -102,7 +101,7 @@ mod test { let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<'_, BorrowedStatic<'_, i32, SyncControlFlow>>>() + .upcast_mut::<dyn Value<'_, BorrowedStatic<'_, i32>>>() .unwrap() .visit(BorrowedStatic(&101)); @@ -113,9 +112,9 @@ mod test { fn visit_borrowed() { struct Visitor<'ctx>(Option<&'ctx mut String>); - impl<'ctx> Value<BorrowedMutStatic<'ctx, String>> for Visitor<'ctx> { + impl<'a, 'ctx> Value<'a, BorrowedMutStatic<'ctx, String>> for Visitor<'ctx> { fn visit( - &mut self, + &'a mut self, BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, ) -> ControlFlow<()> { self.0 = Some(value); @@ -125,7 +124,7 @@ mod test { any_trait! { impl['a, 'ctx] Visitor<'ctx> = [ - dyn Value<BorrowedMutStatic<'ctx, String>> + 'a, + dyn Value<'a, BorrowedMutStatic<'ctx, String>> + 'a, ]; } @@ -134,7 +133,7 @@ mod test { let mut y = String::from("abc"); let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<_>>() + .upcast_mut::<dyn Value<'_, _>>() .unwrap() .visit(BorrowedMutStatic(&mut y)); @@ -146,9 +145,9 @@ mod test { fn visit_borrowed_unsized() { struct Visitor<'ctx>(Option<&'ctx str>); - impl<'ctx> Value<BorrowedStatic<'ctx, str>> for Visitor<'ctx> { + impl<'a, 'ctx> Value<'a, BorrowedStatic<'ctx, str>> for Visitor<'ctx> { fn visit( - &mut self, + &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, str>, ) -> ControlFlow<()> { self.0 = Some(value); @@ -158,7 +157,7 @@ mod test { any_trait! { impl['a, 'ctx] Visitor<'ctx> = [ - dyn Value<BorrowedStatic<'ctx, str>> + 'a, + dyn Value<'a, BorrowedStatic<'ctx, str>> + 'a, ]; } @@ -167,7 +166,7 @@ mod test { let y = String::from("abc"); let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<BorrowedStatic<'_, str>>>() + .upcast_mut::<dyn Value<'_, BorrowedStatic<'_, str>>>() .unwrap() .visit(BorrowedStatic(&y)); diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index abdb136..28bf437 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -29,13 +29,13 @@ pub trait HintMeta<'ctx> { } /// Object implementing the [`Hint`] protocol. -pub trait Hint<'ctx, Protocol: HintMeta<'ctx>, E: Effect = SyncEffect> { +pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E: Effect = SyncEffect> { /// Hint to the walker to use the `P` protocol. /// /// This should only be called once per [`RequestHint`]. fn hint<'a>( &'a mut self, - visitor: &'a mut Visitor<'ctx>, + visitor: &'a mut Visitor<'a, 'ctx>, hint: Protocol::Hint<'a>, ) -> ControlFlowFor<'a, E>; @@ -85,7 +85,7 @@ mod test { impl<'ctx, X> Hint<'ctx, Y> for X { fn hint<'a>( &'a mut self, - visitor: &'a mut Visitor<'ctx>, + visitor: &'a mut Visitor<'a, 'ctx>, hint: <Y as HintMeta<'ctx>>::Hint<'a>, ) -> ControlFlow<()> { todo!() diff --git a/src/walk.rs b/src/walk.rs index 88f3287..d13316d 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,5 +1,4 @@ -// pub mod protocols; -// pub mod walkers; +pub mod walkers; use crate::protocol::{ControlFlowFor, Effect, Visitor}; @@ -38,6 +37,6 @@ pub trait Walker<'ctx> { #[must_use] fn walk<'a>( self, - visitor: &'a mut Visitor<'ctx>, + visitor: &'a mut Visitor<'a, 'ctx>, ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error>; } diff --git a/src/walk/protocols.rs b/src/walk/protocols.rs deleted file mode 100644 index e69de29..0000000 --- a/src/walk/protocols.rs +++ /dev/null diff --git a/src/walk/walkers.rs b/src/walk/walkers.rs index fdab12e..5a7ca06 100644 --- a/src/walk/walkers.rs +++ b/src/walk/walkers.rs @@ -1,13 +1 @@ -use crate::protocol::ProtocolId; - -mod owned; -mod owned_clone; - -mod serde; - -pub use owned::*; -pub use owned_clone::*; - -#[derive(thiserror::Error, Debug)] -#[error("The visitor is missing protocol: {0}")] -pub struct MissingProtocol(pub ProtocolId); +pub mod core; diff --git a/src/walk/walkers/core.rs b/src/walk/walkers/core.rs new file mode 100644 index 0000000..7ea094a --- /dev/null +++ b/src/walk/walkers/core.rs @@ -0,0 +1,2 @@ +pub mod array; +pub mod bool; diff --git a/src/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs new file mode 100644 index 0000000..73777d0 --- /dev/null +++ b/src/walk/walkers/core/array.rs @@ -0,0 +1,95 @@ +use crate::protocol::Effect; +use core::{mem::MaybeUninit, ops::ControlFlow}; + +use crate::{ + any_trait, + protocol::{ + visitor::{RequestHint, Sequence, SequenceScope, Status}, + walker::{Hint, HintMeta}, + ControlFlowFor, SyncEffect, Visitor, + }, +}; + +impl<'ctx, T: crate::Walk<'ctx>, const N: usize> crate::Walk<'ctx> for [T; N] { + type Walker = Walker<'ctx, T, N, T::Walker>; +} + +#[derive(Debug)] +pub struct WalkerError<E> { + pub index: usize, + pub error: E, +} + +pub struct Walker<'ctx, T, const N: usize, W: crate::Walker<'ctx>> { + array: [Option<T>; N], + index: usize, + item_err: Option<(usize, W::Error)>, +} + +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> From<[T; N]> + for Walker<'ctx, T, N, W> +{ + fn from(value: [T; N]) -> Self { + Self { + array: value.map(Some), + index: 0, + item_err: None, + } + } +} + +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> crate::Walker<'ctx> + for Walker<'ctx, T, N, W> +{ + type Effect = SyncEffect; + + type Error = WalkerError<W::Error>; + + type Output = (); + + #[inline] + fn walk<'a>( + mut self, + visitor: &'a mut Visitor<'a, 'ctx>, + ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error> { + SyncEffect::wrap(async { + if let Some(object) = visitor.upcast_mut::<dyn Sequence<'ctx, W::Effect> + '_>() { + object.visit(&mut self).await; + } + + if let Some((index, error)) = self.item_err { + ControlFlow::Break(WalkerError { index, error }) + } else { + ControlFlow::Continue(()) + } + }) + } +} + +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> SequenceScope<'ctx, W::Effect> + for Walker<'ctx, T, N, W> +{ + #[inline] + fn next<'a>( + &'a mut self, + visitor: &'a mut Visitor<'a, 'ctx>, + ) -> ControlFlowFor<'a, W::Effect, Status> { + W::Effect::wrap(async { + if let Some(Some(value)) = self.array.get_mut(self.index).map(Option::take) { + self.index += 1; + + let walker = W::from(value); + + match walker.walk(visitor).await { + ControlFlow::Continue(_) => ControlFlow::Continue(Status::Continue), + ControlFlow::Break(err) => { + self.item_err = Some((self.index, err)); + ControlFlow::Continue(Status::Done) + } + } + } else { + ControlFlow::Continue(Status::Done) + } + }) + } +} diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs new file mode 100644 index 0000000..caa79d2 --- /dev/null +++ b/src/walk/walkers/core/bool.rs @@ -0,0 +1,48 @@ +use crate::{ + any::static_wrapper::OwnedStatic, + protocol::{visitor::Value, Effect}, +}; +use core::{mem::MaybeUninit, ops::ControlFlow}; + +use crate::{ + any_trait, + protocol::{ + visitor::{RequestHint, Sequence, SequenceScope, Status}, + walker::{Hint, HintMeta}, + ControlFlowFor, SyncEffect, Visitor, + }, +}; + +impl<'ctx> crate::Walk<'ctx> for bool { + type Walker = Walker; +} + +pub struct Walker(bool); + +impl<'ctx> From<bool> for Walker { + fn from(value: bool) -> Self { + Self(value) + } +} + +impl<'ctx> crate::Walker<'ctx> for Walker { + type Effect = SyncEffect; + + type Error = (); + + type Output = (); + + #[inline] + fn walk<'a>( + self, + visitor: &'a mut Visitor<'a, 'ctx>, + ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error> { + SyncEffect::wrap(async { + if let Some(object) = visitor.upcast_mut::<dyn Value<'_, OwnedStatic<bool>> + '_>() { + object.visit(OwnedStatic(self.0)).await; + } + + ControlFlow::Continue(()) + }) + } +} diff --git a/src/walk/walkers/owned.rs b/src/walk/walkers/owned.rs deleted file mode 100644 index 6703625..0000000 --- a/src/walk/walkers/owned.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::{ - build::protocols, - protocol::{Implementer, ImplementerExt, ProtocolExt}, - Walker, -}; - -use super::MissingProtocol; - -pub struct OwnedWalker<T> { - value: T, -} - -impl<T> OwnedWalker<T> { - pub const fn new(value: T) -> Self { - Self { value } - } -} - -impl<T> From<T> for OwnedWalker<T> { - fn from(value: T) -> Self { - Self::new(value) - } -} - -impl<'ctx, T: 'static> Walker<'ctx> for OwnedWalker<T> { - type Error = (MissingProtocol, T); - - type Value = (); - - fn walk(self, visitor: &mut dyn Implementer<'ctx>) -> Result<Self::Value, Self::Error> { - if let Some(interface) = visitor.interface_for::<protocols::owned::Owned<T>>() { - let _ = interface.as_object().visit(self.value); - Ok(()) - } else { - Err(( - MissingProtocol(protocols::owned::Owned::<T>::id()), - self.value, - )) - } - } -} diff --git a/src/walk/walkers/owned_clone.rs b/src/walk/walkers/owned_clone.rs deleted file mode 100644 index 27a323e..0000000 --- a/src/walk/walkers/owned_clone.rs +++ /dev/null @@ -1,217 +0,0 @@ -use crate::build::protocols; -use crate::protocol::Implementer; -use crate::protocol::{ImplementerExt, ProtocolExt}; -use crate::{implementer, walk, Walker}; - -use super::MissingProtocol; - -pub struct OwnedCloneWalker<T> { - value: Option<T>, - error: Option<MissingProtocol>, - hint_given: bool, -} - -impl<T> OwnedCloneWalker<T> { - pub const fn new(value: T) -> Self { - Self { - value: Some(value), - error: None, - hint_given: false, - } - } -} - -impl<T> From<T> for OwnedCloneWalker<T> { - fn from(value: T) -> Self { - Self::new(value) - } -} - -impl<'ctx, T: 'static + Clone> Walker<'ctx> for OwnedCloneWalker<T> { - type Error = MissingProtocol; - - type Value = (); - - fn walk(mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<Self::Value, Self::Error> { - // Request the visitor give a hint. - // This allows the use of the recoverable protocol. - if let Some(interface) = visitor.interface_for::<protocols::hint::RequestHint>() { - match interface.as_object().request_hint(&mut self) { - Ok(()) => {} - Err(()) => { - return match self.error { - Some(err) => Err(err), - None => Ok(()), - }; - } - } - } - - // If no hint was given then just use the owned protocol. - if !self.hint_given { - let _ = walk::protocols::hint::Object::<protocols::owned::Owned<T>>::hint( - &mut self, - visitor, - (), - ); - } - - // Return an error if there was one. - match self.error { - Some(err) => Err(err), - None => Ok(()), - } - } -} - -implementer! { - impl['ctx, T: 'static + Clone] OwnedCloneWalker<T> = [ - walk::protocols::hint::Hint<protocols::owned::Owned<T>>, - walk::protocols::hint::Hint<protocols::recoverable::Recoverable>, - walk::protocols::hint::Hint<protocols::borrowed::Borrowed<T>>, - walk::protocols::hint::Hint<protocols::borrowed_mut::BorrowedMut<T>>, - ]; -} - -impl<'ctx, T: 'static + Clone> walk::protocols::hint::Object<'ctx, protocols::owned::Owned<T>> - for OwnedCloneWalker<T> -{ - fn hint(&mut self, visitor: &mut dyn Implementer<'ctx>, _hint: ()) -> Result<(), ()> { - self.hint_given = true; - - if let Some(interface) = visitor.interface_for::<protocols::owned::Owned<T>>() { - // If this happens it means the value was already visited and consumed. - let Some(value) = self.value.take() else { - return Ok(()); // We return Ok because the walker isn't in an error state. - }; - - // Visit the value. - interface.as_object().visit(value) - } else { - self.error = Some(MissingProtocol(protocols::owned::Owned::<T>::id())); - Err(()) - } - } - - fn known(&mut self, _hint: &()) -> Result<(), ()> { - Ok(()) - } -} - -impl<'ctx, T: 'static + Clone> walk::protocols::hint::Object<'ctx, protocols::borrowed::Borrowed<T>> - for OwnedCloneWalker<T> -{ - fn hint( - &mut self, - visitor: &mut dyn Implementer<'ctx>, - _hint: protocols::borrowed::Hint, - ) -> Result<(), ()> { - self.hint_given = true; - - if let Some(interface) = visitor.interface_for::<protocols::borrowed::Borrowed<T>>() { - // If this happens it means the value was already visited and consumed. - let Some(value) = &self.value else { - return Ok(()); // We return Ok because the walker isn't in an error state. - }; - - // Visit the value. - interface.as_object().visit(protocols::borrowed::Value::Temp(value)) - } else { - self.error = Some(MissingProtocol(protocols::owned::Owned::<T>::id())); - Err(()) - } - } - - fn known( - &mut self, - _hint: &protocols::borrowed::Hint, - ) -> Result<protocols::borrowed::Known, ()> { - Ok(protocols::borrowed::Known { - kind: Some(protocols::borrowed::Kind::Temp), - }) - } -} - -impl<'ctx, T: 'static + Clone> walk::protocols::hint::Object<'ctx, protocols::borrowed_mut::BorrowedMut<T>> - for OwnedCloneWalker<T> -{ - fn hint( - &mut self, - visitor: &mut dyn Implementer<'ctx>, - _hint: protocols::borrowed_mut::Hint, - ) -> Result<(), ()> { - self.hint_given = true; - - if let Some(interface) = visitor.interface_for::<protocols::borrowed_mut::BorrowedMut<T>>() { - // If this happens it means the value was already visited and consumed. - let Some(value) = &mut self.value else { - return Ok(()); // We return Ok because the walker isn't in an error state. - }; - - // Visit the value. - interface.as_object().visit(protocols::borrowed_mut::Value::Temp(value)) - } else { - self.error = Some(MissingProtocol(protocols::owned::Owned::<T>::id())); - Err(()) - } - } - - fn known( - &mut self, - _hint: &protocols::borrowed_mut::Hint, - ) -> Result<protocols::borrowed_mut::Known, ()> { - Ok(protocols::borrowed_mut::Known { - kind: Some(protocols::borrowed_mut::Kind::Temp), - }) - } -} - -impl<'ctx, T: 'static + Clone> - walk::protocols::hint::Object<'ctx, protocols::recoverable::Recoverable> - for OwnedCloneWalker<T> -{ - fn hint(&mut self, visitor: &mut dyn Implementer<'ctx>, _hint: ()) -> Result<(), ()> { - self.hint_given = true; - - if let Some(interface) = visitor.interface_for::<protocols::recoverable::Recoverable>() { - // This walker is already recoverable. - interface.as_object().visit(self) - } else { - self.error = Some(MissingProtocol(protocols::recoverable::Recoverable::id())); - Err(()) - } - } - - fn known(&mut self, _hint: &()) -> Result<(), ()> { - Ok(()) - } -} - -impl<'ctx, T: 'static + Clone> protocols::recoverable::RecoverableWalker<'ctx> - for OwnedCloneWalker<T> -{ - fn new_walk(&mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<(), ()> { - // Short circuit if the walker has an error. - if self.error.is_some() { - return Err(()); - } - - // Short circuit if the walker doesn't have a value. - // If this happens it means the value was already visited and consumed. - let Some(value) = &self.value else { - return Ok(()); // We return Ok because the walker isn't in an error state. - }; - - // Clone the value to put into a new walker instance. - let walker = Self::new(value.clone()); - - // Walk the walker. - match walker.walk(visitor) { - Ok(()) => Ok(()), // We don't know if the visitor had an issue. - Err(err) => { - self.error = Some(err); - Err(()) - } - } - } -} diff --git a/tests/async.rs b/tests/async.rs index 2c446a1..13968ab 100644 --- a/tests/async.rs +++ b/tests/async.rs @@ -50,7 +50,7 @@ const _: () = { type Output = (); - fn walk<'a>(self, visitor: &'a mut Visitor<'ctx>) -> ControlFlowFor<'a, AsyncEffect> { + fn walk<'a>(self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, AsyncEffect> { Box::pin(async { match self.0 { Data::Bool(value) => walk_bool(value, visitor), @@ -62,20 +62,20 @@ const _: () = { } }; -fn walk_bool(value: bool, visitor: &mut Visitor<'_>) { +fn walk_bool(value: bool, visitor: &mut Visitor<'_, '_>) { visitor .upcast_mut::<dyn Value<OwnedStatic<bool>>>() .unwrap() .visit(OwnedStatic(value)); } -async fn walk_vec(value: Vec<Data>, visitor: &mut Visitor<'_>) { +async fn walk_vec(value: Vec<Data>, visitor: &mut Visitor<'_, '_>) { struct Scope(VecDeque<Data>); impl<'ctx> SequenceScope<'ctx, AsyncEffect> for Scope { fn next<'a>( &'a mut self, - visitor: &'a mut Visitor<'ctx>, + visitor: &'a mut Visitor<'a, 'ctx>, ) -> ControlFlowFor<'a, AsyncEffect, Status> { Box::pin(async { if let Some(value) = self.0.pop_front() { @@ -106,7 +106,7 @@ impl<'ctx> Builder<'ctx> for JsonLike { type Value = String; - fn as_visitor(&mut self) -> &mut Visitor<'ctx> { + fn as_visitor(&mut self) -> &mut Visitor<'_, 'ctx> { self } diff --git a/tests/demo.rs b/tests/demo.rs index 9baf602..0f0e190 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -1,10 +1,12 @@ use std::{collections::VecDeque, ops::ControlFlow}; use treaty::{ any::{any_trait, static_wrapper::OwnedStatic}, - build_with, into_walker, + build, build_with, + builders::core::array, + into_walker, protocol::{ visitor::{Sequence, SequenceScope, Value}, - SyncEffect, Visitor, + ControlFlowFor, Ready, SyncEffect, Visitor, }, Builder, Walk, Walker, }; @@ -17,9 +19,20 @@ fn demo() { Data::Bool(false), ]); - let s = build_with::<JsonLike, _>(into_walker(a)).unwrap(); + // dbg!(array_to_array([true, false, true])); - assert_eq!(s, "[true,[false,true,],false,]"); + let s = build_with::<array::Builder<'_, JsonLike, 3>, _>(into_walker(&a)).unwrap(); + dbg!(s); + + // let s = build_with::<JsonLike, _>(into_walker(a)).unwrap(); + + todo!(); + // assert_eq!(s, "[true,[false,true,],false,]"); +} + +#[no_mangle] +pub fn array_to_array(x: [bool; 1]) -> [bool; 1] { + unsafe { build(into_walker(x)).unwrap_unchecked() } } #[derive(Debug)] @@ -29,64 +42,68 @@ enum Data { } const _: () = { - struct Impl(Data); + struct Impl<'ctx>(&'ctx Data); - impl From<Data> for Impl { - fn from(value: Data) -> Self { + impl<'ctx> From<&'ctx Data> for Impl<'ctx> { + fn from(value: &'ctx Data) -> Self { Self(value) } } - impl<'ctx> Walk<'ctx> for Data { - type Walker = Impl; + impl<'ctx> Walk<'ctx> for &'ctx Data { + type Walker = Impl<'ctx>; } - impl<'ctx> Walker<'ctx> for Impl { + impl<'ctx> Walker<'ctx> for Impl<'ctx> { type Effect = SyncEffect; type Error = (); type Output = (); - fn walk( + fn walk<'a>( self, - visitor: &mut Visitor<'ctx>, - ) -> core::ops::ControlFlow<Self::Error, Self::Output> { + visitor: &'a mut Visitor<'a, 'ctx>, + ) -> ControlFlowFor<'a, SyncEffect, Self::Error, Self::Output> { match self.0 { - Data::Bool(value) => walk_bool(value, visitor), + Data::Bool(value) => walk_bool(*value, visitor), Data::Sequence(value) => walk_vec(value, visitor), } - core::ops::ControlFlow::Continue(()) + Ready::new(core::ops::ControlFlow::Continue(())) } } }; -fn walk_bool(value: bool, visitor: &mut Visitor<'_>) { +fn walk_bool(value: bool, visitor: &mut Visitor<'_, '_>) { visitor .upcast_mut::<dyn Value<OwnedStatic<bool>>>() .unwrap() .visit(OwnedStatic(value)); } -fn walk_vec(value: Vec<Data>, visitor: &mut Visitor<'_>) { - struct Scope(VecDeque<Data>); +fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: &'a mut Visitor<'a, 'ctx>) { + struct Scope<'ctx>(VecDeque<&'ctx Data>); - impl<'ctx> SequenceScope<'ctx> for Scope { - fn next( - &mut self, - visitor: &mut Visitor<'ctx>, - ) -> core::ops::ControlFlow<(), treaty::protocol::visitor::Status> { + impl<'ctx> SequenceScope<'ctx> for Scope<'ctx> { + fn next<'a>( + &'a mut self, + visitor: &'a mut Visitor<'a, 'ctx>, + ) -> ControlFlowFor<'a, SyncEffect, treaty::protocol::visitor::Status> { if let Some(value) = self.0.pop_front() { into_walker(value).walk(visitor); - ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) + Ready::new(ControlFlow::Continue( + treaty::protocol::visitor::Status::Continue, + )) } else { - ControlFlow::Continue(treaty::protocol::visitor::Status::Done) + Ready::new(ControlFlow::Continue( + treaty::protocol::visitor::Status::Done, + )) } } } - let mut scope = Scope(value.into()); + let mut scope = Scope(value.into_iter().collect()); visitor .upcast_mut::<dyn Sequence<'_>>() @@ -102,7 +119,7 @@ impl<'ctx> Builder<'ctx> for JsonLike { type Value = String; - fn as_visitor(&mut self) -> &mut Visitor<'ctx> { + fn as_visitor(&mut self) -> &mut Visitor<'_, 'ctx> { self } @@ -119,21 +136,24 @@ any_trait! { } impl Value<'_, OwnedStatic<bool>> for JsonLike { - fn visit(&mut self, value: OwnedStatic<bool>) -> core::ops::ControlFlow<()> { + fn visit(&mut self, value: OwnedStatic<bool>) -> ControlFlowFor<'_> { self.0.push_str(&format!("{}", value.0)); - ControlFlow::Continue(()) + Ready::new(ControlFlow::Continue(())) } } impl<'ctx> Sequence<'ctx> for JsonLike { - fn visit(&mut self, scope: &mut dyn SequenceScope<'ctx>) -> core::ops::ControlFlow<()> { + fn visit<'a>( + &'a mut self, + scope: &'a mut dyn SequenceScope<'ctx>, + ) -> ControlFlowFor<'a, SyncEffect> { self.0.push_str("["); while let ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) = - scope.next(self) + scope.next(self).into_inner() { self.0.push_str(","); } self.0.push_str("]"); - ControlFlow::Continue(()) + Ready::new(ControlFlow::Continue(())) } } |