Diffstat (limited to 'src/build.rs')
-rw-r--r--src/build.rs161
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!();
+ }
+}