-rw-r--r--Cargo.toml2
-rw-r--r--src/build.rs20
-rw-r--r--src/build/builders.rs8
-rw-r--r--src/build/builders/core.rs2
-rw-r--r--src/build/builders/core/array.rs128
-rw-r--r--src/build/builders/core/bool.rs54
-rw-r--r--src/build/builders/owned.rs56
-rw-r--r--src/build/protocols.rs195
-rw-r--r--src/impls/alloc.rs1
-rw-r--r--src/impls/alloc/string.rs213
-rw-r--r--src/impls/core.rs5
-rw-r--r--src/impls/core/bool.rs17
-rw-r--r--src/impls/core/iterator.rs76
-rw-r--r--src/impls/core/reference.rs244
-rw-r--r--src/impls/core/reference_mut.rs162
-rw-r--r--src/impls/core/str.rs63
-rw-r--r--src/lib.rs1
-rw-r--r--src/protocol.rs78
-rw-r--r--src/protocol/visitor/borrow.rs116
-rw-r--r--src/protocol/visitor/request_hint.rs2
-rw-r--r--src/protocol/visitor/sequence.rs2
-rw-r--r--src/protocol/visitor/tagged.rs4
-rw-r--r--src/protocol/visitor/value.rs29
-rw-r--r--src/protocol/walker/hint.rs6
-rw-r--r--src/walk.rs5
-rw-r--r--src/walk/protocols.rs0
-rw-r--r--src/walk/walkers.rs14
-rw-r--r--src/walk/walkers/core.rs2
-rw-r--r--src/walk/walkers/core/array.rs95
-rw-r--r--src/walk/walkers/core/bool.rs48
-rw-r--r--src/walk/walkers/owned.rs41
-rw-r--r--src/walk/walkers/owned_clone.rs217
-rw-r--r--tests/async.rs10
-rw-r--r--tests/demo.rs84
34 files changed, 500 insertions, 1500 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7930439..8972d74 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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)
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index fb044d8..831d875 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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(()))
}
}