use core::{marker::PhantomData, mem::MaybeUninit, ops::ControlFlow}; use crate::{ any_trait, effect::{AsObj as _, Effect, EffectAnyTrait, SyncEffect, Yield}, protocol::visitor::{Sequence, SequenceScope, Status}, AsVisitor, DefaultBuilder, }; #[cfg(feature = "alloc")] use crate::effect::AsyncEffect; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; impl<'ctx, T, const N: usize, E: EffectAnyTrait<'ctx>> crate::Build<'ctx, E> for [T; N] where T: crate::Build<'ctx, E>, >::Builder: DefaultBuilder<'ctx, E>, Builder<'ctx, T::Builder, N, E>: AsVisitor<'ctx, E>, { type Builder = Builder<'ctx, T::Builder, N, E>; } #[derive(Debug)] pub enum ArrayError { Incomplete, Item(usize, E), } pub struct Builder<'ctx, B: crate::Builder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> { array: MaybeUninit<[B::Value; N]>, index: usize, item_err: Option<(usize, B::Error)>, _marker: PhantomData E>, } impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> crate::Builder<'ctx, E> for Builder<'ctx, B, N, E> where Self: AsVisitor<'ctx, E>, { type Error = ArrayError; type Value = [B::Value; N]; fn build<'a>(self) -> Result where Self: 'a, { 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() }) } } type Seed = (); fn from_seed(seed: Self::Seed) -> Self { Self { array: MaybeUninit::uninit(), index: 0, item_err: None, _marker: PhantomData, } } type Effect = SyncEffect; } impl<'ctx, B: crate::DefaultBuilder<'ctx, SyncEffect>, const N: usize> AsVisitor<'ctx, SyncEffect> for Builder<'ctx, B, N, SyncEffect> where B: crate::Builder<'ctx, SyncEffect, Effect = SyncEffect>, { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { self } } // #[cfg(not(feature = "alloc"))] any_trait! { impl['a, 'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'ctx, ControlFlow<(), ()>>] Builder<'ctx, B, N, E> = [ dyn Sequence<'ctx, SyncEffect> + 'a, ] where B: crate::Builder<'ctx, E, Effect = SyncEffect> } // #[cfg(feature = "alloc")] // any_trait! { // impl['a, 'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ // dyn Sequence<'ctx> + 'a, // dyn Sequence<'ctx, AsyncEffect> + 'a, // ] // } impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> Sequence<'ctx, SyncEffect> for Builder<'ctx, B, N, E> where B: crate::Builder<'ctx, E, Effect = SyncEffect>, { #[inline] fn visit<'a>( &'a mut self, scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>, ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> where 'ctx: '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().into_obj()) { 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) // }; unsafe { let ptr = (self.array.as_mut_ptr() as *mut B::Value).offset(self.index as _); core::ptr::write(ptr, value); } // 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( // array: &mut MaybeUninit<[T; N]>, // ) -> &mut [MaybeUninit; N] { // unsafe { &mut *(array as *mut _ as *mut [MaybeUninit; N]) } // }