| -rw-r--r-- | src/any/static_wrapper.rs | 5 | ||||
| -rw-r--r-- | src/build.rs | 4 | ||||
| -rw-r--r-- | src/build/builders/core/array.rs | 77 | ||||
| -rw-r--r-- | src/build/builders/core/bool.rs | 13 | ||||
| -rw-r--r-- | src/protocol.rs | 55 | ||||
| -rw-r--r-- | src/walk/walkers/core/array.rs | 52 | ||||
| -rw-r--r-- | src/walk/walkers/core/bool.rs | 6 | ||||
| -rw-r--r-- | tests/demo.rs | 32 |
8 files changed, 105 insertions, 139 deletions
diff --git a/src/any/static_wrapper.rs b/src/any/static_wrapper.rs index ce26fdd..d167257 100644 --- a/src/any/static_wrapper.rs +++ b/src/any/static_wrapper.rs @@ -3,6 +3,7 @@ use super::*; /// Impl of [`TypeNameable`] for `'static` types that are owned (`T`). +#[repr(transparent)] pub struct OwnedStatic<T: ?Sized>(pub T); nameable! { @@ -12,6 +13,7 @@ nameable! { } /// Impl of [`TypeNameable`] for `'static` types that are borrowed (`&'lt T`). +#[repr(transparent)] pub struct BorrowedStatic<'lt, T: ?Sized>(pub &'lt T); nameable! { @@ -21,6 +23,7 @@ nameable! { } /// Impl of [`TypeNameable`] for `'static` types that are temporarily borrowed (`&'a T`). +#[repr(transparent)] pub struct TempBorrowedStatic<'a, T: ?Sized>(pub &'a T); nameable! { @@ -30,6 +33,7 @@ nameable! { } /// Impl of [`TypeNameable`] for `'static` types that are borrowed mutably (`&'lt mut T`). +#[repr(transparent)] pub struct BorrowedMutStatic<'lt, T: ?Sized>(pub &'lt mut T); nameable! { @@ -39,6 +43,7 @@ nameable! { } /// Impl of [`TypeNameable`] for `'static` types that are temporarily borrowed mutably (`&'a mut T`). +#[repr(transparent)] pub struct TempBorrowedMutStatic<'a, T: ?Sized>(pub &'a mut T); nameable! { diff --git a/src/build.rs b/src/build.rs index 87c0fc8..f0bb597 100644 --- a/src/build.rs +++ b/src/build.rs @@ -55,7 +55,7 @@ pub fn build<'ctx, T: Build<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( ) -> 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() { + if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { return Err(BuildError::Walker(err)); } @@ -67,7 +67,7 @@ pub fn build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( ) -> 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()).into_inner() { + if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { return Err(BuildError::Walker(err)); } diff --git a/src/build/builders/core/array.rs b/src/build/builders/core/array.rs index 2b8edb3..f3311e5 100644 --- a/src/build/builders/core/array.rs +++ b/src/build/builders/core/array.rs @@ -4,7 +4,7 @@ use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status}, - ControlFlowFor, Effect, Ready, + ControlFlowFor, Effect, }, }; @@ -80,49 +80,56 @@ any_trait! { ]; } -impl<'ctx, B: crate::Builder<'ctx>, const N: usize, E: Effect> Sequence<'ctx, E> +impl<'ctx, B: crate::Builder<'ctx>, const N: usize> Sequence<'ctx> 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 { + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { + 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()) { + 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(()); } - - // 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::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) + // }; + unsafe { + let ptr = (self.array.as_mut_ptr() as *mut B::Value).offset(self.index as _); + core::ptr::write(ptr, value); } - }, - ControlFlow::Break(()) => { + // std::ptr::write(&mut self.array + 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]) } -} +// +// 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 index dd98d0e..ebf628c 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -3,7 +3,7 @@ use core::ops::ControlFlow; use crate::{ any::static_wrapper::OwnedStatic, any_trait, - protocol::{visitor::Value, ControlFlowFor, Effect}, + protocol::{visitor::Value, ControlFlowFor, Effect, SyncEffect}, }; impl<'ctx> crate::Build<'ctx> for bool { @@ -32,6 +32,7 @@ impl<'ctx> crate::Builder<'ctx> for Builder { self } + #[inline] fn build(self) -> Result<Self::Value, Self::Error> { self.0.ok_or(Error::Incomplete) } @@ -43,12 +44,10 @@ any_trait! { ]; } -impl<'a, E: Effect> Value<'a, OwnedStatic<bool>, E> for Builder { +impl<'a> Value<'a, OwnedStatic<bool>> 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(()) - }) + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + self.0 = Some(value); + ControlFlow::Continue(()) } } diff --git a/src/protocol.rs b/src/protocol.rs index 37bcee7..c763730 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -52,11 +52,7 @@ 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>>; - - fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( - future: F, - ) -> Self::ControlFlow<'a, C, B>; + type ControlFlow<'a, C, B>; } pub type ControlFlowFor<'a, E = SyncEffect, C = (), B = ()> = <E as Effect>::ControlFlow<'a, C, B>; @@ -64,20 +60,7 @@ pub type ControlFlowFor<'a, E = SyncEffect, C = (), B = ()> = <E as Effect>::Con pub enum SyncEffect {} impl Effect for SyncEffect { - 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"), - } - } + type ControlFlow<'a, C, B> = core::ops::ControlFlow<B, C>; } fn noop() -> Waker { @@ -94,38 +77,4 @@ 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/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs index 73777d0..2709135 100644 --- a/src/walk/walkers/core/array.rs +++ b/src/walk/walkers/core/array.rs @@ -10,7 +10,10 @@ use crate::{ }, }; -impl<'ctx, T: crate::Walk<'ctx>, const N: usize> crate::Walk<'ctx> for [T; N] { +impl<'ctx, T: crate::Walk<'ctx>, const N: usize> crate::Walk<'ctx> for [T; N] +where + <T as crate::Walk<'ctx>>::Walker: crate::Walker<'ctx, Effect = SyncEffect> +{ type Walker = Walker<'ctx, T, N, T::Walker>; } @@ -38,7 +41,7 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> From<[T; N]> } } -impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> crate::Walker<'ctx> +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> crate::Walker<'ctx> for Walker<'ctx, T, N, W> { type Effect = SyncEffect; @@ -52,21 +55,19 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> crate::Walker<'c 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(object) = visitor.upcast_mut::<dyn Sequence<'ctx, W::Effect> + '_>() { + object.visit(&mut self); + } - if let Some((index, error)) = self.item_err { - ControlFlow::Break(WalkerError { index, error }) - } else { - ControlFlow::Continue(()) - } - }) + 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> +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> SequenceScope<'ctx> for Walker<'ctx, T, N, W> { #[inline] @@ -74,22 +75,21 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> SequenceScope<'c &'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; + if self.index >= N { + return ControlFlow::Continue(Status::Done); + } - let walker = W::from(value); + let value = unsafe { self.array.get_unchecked_mut(self.index).take().unwrap_unchecked() }; + self.index += 1; - 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 { + let walker = W::from(value); + + match walker.walk(visitor) { + ControlFlow::Continue(_) => ControlFlow::Continue(Status::Continue), + ControlFlow::Break(err) => { + self.item_err = Some((self.index, err)); ControlFlow::Continue(Status::Done) } - }) + } } } diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs index caa79d2..7d1aca3 100644 --- a/src/walk/walkers/core/bool.rs +++ b/src/walk/walkers/core/bool.rs @@ -37,12 +37,12 @@ impl<'ctx> crate::Walker<'ctx> for Walker { 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; + object.visit(OwnedStatic(self.0)); } ControlFlow::Continue(()) - }) + } } } diff --git a/tests/demo.rs b/tests/demo.rs index 0f0e190..6db1559 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -6,7 +6,7 @@ use treaty::{ into_walker, protocol::{ visitor::{Sequence, SequenceScope, Value}, - ControlFlowFor, Ready, SyncEffect, Visitor, + ControlFlowFor, SyncEffect, Visitor, }, Builder, Walk, Walker, }; @@ -19,7 +19,8 @@ fn demo() { Data::Bool(false), ]); - // dbg!(array_to_array([true, false, true])); + dbg!(array_to_array2([true, false])); + dbg!(array_to_array([true, true])); let s = build_with::<array::Builder<'_, JsonLike, 3>, _>(into_walker(&a)).unwrap(); dbg!(s); @@ -30,9 +31,14 @@ fn demo() { // 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() } +#[inline(never)] +pub fn array_to_array(x: [bool; 2]) -> [bool; 2] { + build(into_walker(x)).unwrap() +} + +#[inline(never)] +pub fn array_to_array2(x: [bool; 2]) -> [bool; 2] { + array_to_array(x) } #[derive(Debug)] @@ -69,7 +75,7 @@ const _: () = { Data::Bool(value) => walk_bool(*value, visitor), Data::Sequence(value) => walk_vec(value, visitor), } - Ready::new(core::ops::ControlFlow::Continue(())) + core::ops::ControlFlow::Continue(()) } } }; @@ -92,13 +98,13 @@ fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: &'a mut Visitor<'a, 'ctx>) { if let Some(value) = self.0.pop_front() { into_walker(value).walk(visitor); - Ready::new(ControlFlow::Continue( + ControlFlow::Continue( treaty::protocol::visitor::Status::Continue, - )) + ) } else { - Ready::new(ControlFlow::Continue( + ControlFlow::Continue( treaty::protocol::visitor::Status::Done, - )) + ) } } } @@ -138,7 +144,7 @@ any_trait! { impl Value<'_, OwnedStatic<bool>> for JsonLike { fn visit(&mut self, value: OwnedStatic<bool>) -> ControlFlowFor<'_> { self.0.push_str(&format!("{}", value.0)); - Ready::new(ControlFlow::Continue(())) + ControlFlow::Continue(()) } } @@ -149,11 +155,11 @@ impl<'ctx> Sequence<'ctx> for JsonLike { ) -> ControlFlowFor<'a, SyncEffect> { self.0.push_str("["); while let ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) = - scope.next(self).into_inner() + scope.next(self) { self.0.push_str(","); } self.0.push_str("]"); - Ready::new(ControlFlow::Continue(())) + ControlFlow::Continue(()) } } |