Diffstat (limited to 'src/build.rs')
| -rw-r--r-- | src/build.rs | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/build.rs b/src/build.rs index 24232a0..0f70423 100644 --- a/src/build.rs +++ b/src/build.rs @@ -52,3 +52,164 @@ pub trait Builder<'ctx, E: Effect<'ctx>>: BuilderTypes + Sized + Send { /// This is expected to just be `self`. fn as_visitor(&mut self) -> Visitor<'_, 'ctx>; } + +#[cfg(test)] +pub mod test { + use std::{collections::HashMap, sync::{Mutex, MutexGuard, PoisonError}}; + + use crate::{ + any::{static_wrapper::OwnedStatic, AnyTrait, Indirect, IndirectLtAny, LtTypeId, Mut, Ref, TypeNameable}, effect::{BlockOn, Blocking, Spin}, protocol::visitor::value::{DynValue, Value}, Flow + }; + + use super::*; + + use mockall::mock; + use mockall::predicate::eq; + + pub mod mock { + use std::collections::HashMap; + + use super::*; + + mock! { + pub Builder<Seed: 'static, Value: 'static, Error: 'static> { + pub fn private_from_seed(seed: Seed) -> Self; + pub fn private_build(self) -> Result<Value, Error>; + + // pub fn private_upcast_to_id(&self, id: LtTypeId<'static>) -> Option<Box<dyn for<'a> MockIndirect>>; + // pub fn private_upcast_to_id_mut(&mut self, id: LtTypeId<'static>) -> Option<Box<dyn for<'a> MockIndirect<'a, Mut>>>; + + pub fn lookup(&self) -> &HashMap<LtTypeId<'static>, Box<dyn MockIndirect>>; + pub fn lookup_mut(&mut self) -> &mut HashMap<LtTypeId<'static>, Box<dyn MockIndirect>>; + } + } + } + + pub type MockBuilder<Seed = (), Value = (), Error = ()> = mock::MockBuilder<Seed, Value, Error>; + + trait MockIndirect: Send { + fn indirect(&self) -> IndirectLtAny<'_, 'static, Ref>; + fn indirect_mut(&mut self) -> IndirectLtAny<'_, 'static, Mut>; + } + + impl<T: ?Sized + for<'a> TypeNameable<'a, 'static> + Send> MockIndirect for Box<T> { + fn indirect(&self) -> IndirectLtAny<'_, 'static, Ref> { + IndirectLtAny::new(self) + } + + fn indirect_mut(&mut self) -> IndirectLtAny<'_, 'static, Mut> { + IndirectLtAny::new(self) + } + } + + impl<Seed: Send, Value: Send, Error: Send> BuilderTypes for MockBuilder<Seed, Value, Error> { + type Seed = Seed; + + type Error = Error; + + type Value = Value; + } + + impl<Seed, Value, Error> MockBuilder<Seed, Value, Error> { + pub fn lock_context<'a>() -> MutexGuard<'a, ()> { + static LOCK: Mutex<()> = Mutex::new(()); + LOCK.lock().unwrap_or_else(PoisonError::into_inner) + } + } + + impl<Seed: Send, Value: Send, Error: Send, E: Effect<'static>> Builder<'static, E> for MockBuilder<Seed, Value, Error> { + fn from_seed<'a>(seed: Self::Seed) -> Future<'a, 'static, Self, E> + where + Self: 'a, + { + E::ready(Self::private_from_seed(seed)) + } + + fn build<'a>(self) -> Future<'a, 'static, Result<Self::Value, Self::Error>, E> + where + Self: 'a, + { + E::ready(self.private_build()) + } + + fn as_visitor(&mut self) -> Visitor<'_, 'static> { + self + } + } + + impl<Seed, Value, Error> AnyTrait<'static> for MockBuilder<Seed, Value, Error> { + fn upcast_to_id<'a>( + &'a self, + id: LtTypeId<'static>, + ) -> Option<IndirectLtAny<'a, 'static, Ref>> + where + 'static: 'a, + { + self.lookup().get(&id).map(|x| x.indirect()) + } + + fn upcast_to_id_mut<'a>( + &'a mut self, + id: LtTypeId<'static>, + ) -> Option<IndirectLtAny<'a, 'static, Mut>> + where + 'static: 'a, + { + self.lookup_mut().get_mut(&id).map(|x| x.indirect_mut()) + } + } + + mock! { + ValueVisitor { + fn private_visit(&mut self, value: OwnedStatic<i32>) -> Flow; + } + } + + impl<'ctx, E: Effect<'ctx>> Value<'ctx, OwnedStatic<i32>, E> for MockValueVisitor { + fn visit<'a>(&'a mut self, value: OwnedStatic<i32>) -> Future<'a, 'ctx, Flow, E> { + E::ready(self.private_visit(value)) + } + } + + #[test] + fn demo2() { + let _lock = MockBuilder::<(), (), ()>::lock_context(); + let ctx = MockBuilder::<(), (), ()>::private_from_seed_context(); + + ctx.expect().once().returning(|_| { + let mut mock = MockBuilder::new(); + + mock.expect_lookup_mut().returning(|| { + let mut map = HashMap::<_, Box<dyn MockIndirect>>::new(); + + map.insert( + LtTypeId::of::<DynValue<'_, 'static, OwnedStatic<i32>, Blocking>>(), + Box::new(Box::new(MockValueVisitor::new()) as Box<DynValue<'_, 'static, OwnedStatic<i32>, Blocking>>) + ); + + map + }); + + mock.expect_private_build().once().returning(|| { + Ok(()) + }); + + mock + }); + + let mut builder = Spin::block_on(<MockBuilder as Builder<Blocking>>::from_seed(())); + + { + let visitor = <MockBuilder as Builder<Blocking>>::as_visitor(&mut builder); + + let x = visitor.upcast_to_id_mut(LtTypeId::of::<DynValue<'_, '_, OwnedStatic<i32>, Blocking>>()).unwrap(); + let Ok(x) = x.downcast::<DynValue<'_, '_, OwnedStatic<i32>, Blocking>>() else { + panic!(); + }; + Spin::block_on(x.visit(OwnedStatic(42))); + } + + let x = <MockBuilder as Builder<Blocking>>::build(builder); + todo!(); + } +} |