use core::any::type_name;
use crate::any::type_name::{Lowered, Raised};
use crate::any::{BorrowedStatic, MutAnyUnsized, OwnedStatic};
use crate::protocol::DynWalker;
use effectful::effective::Canonical;
use effectful::{DynBind, Effective, Environment, SendSync};
use crate::protocol::visitor::{request_hint, visit_value, RequestHint, Value, VisitResult};
use crate::trait_by_id;
use crate::{
any::AnyTrait,
build::BuilderTypes,
hkt::Marker,
protocol::{AsVisitor, DynVisitor},
Builder,
};
#[derive(SendSync)]
pub struct Tracer<B, E> {
inner: B,
_env: Marker<E>,
}
impl<B, E: Environment> BuilderTypes<E> for Tracer<B, E>
where
B: BuilderTypes<E>,
{
type Seed = B::Seed;
type Error = B::Error;
type Output = B::Output;
type Value = B::Value;
fn unwrap_output(output: Self::Output) -> Self::Value {
println!("Unwrapped output value");
B::unwrap_output(output)
}
}
impl<'src, B, E: Environment> Builder<'src, E> for Tracer<B, E>
where
B: Builder<'src, E>,
{
fn from_seed<'u>(seed: Self::Seed) -> effectful::effective::Canonical<'u, Self, E>
where
Self: 'u,
{
println!("Created builder from seed value: {}", type_name::<B>());
B::from_seed(seed)
.map((), |_, b| Self {
inner: b,
_env: Marker::NEW,
})
.cast()
}
fn build<'u>(self) -> effectful::effective::Canonical<'u, Result<Self::Output, Self::Error>, E>
where
Self: 'u,
{
println!("Built value");
self.inner.build()
}
}
impl<'src, B, E: Environment> AsVisitor<'src, E> for Tracer<B, E>
where
Self: DynBind<E> + AnyTrait<'src>,
{
fn as_visitor(&mut self) -> crate::protocol::DynVisitor<'_, 'src, E> {
println!("Converted builder to visitor");
DynVisitor::new(self)
}
}
impl<'src, B, E: Environment> AnyTrait<'src> for Tracer<B, E>
where
B: AsVisitor<'src, E>,
Self: Value<'src, OwnedStatic<i32>, E>
+ Value<'src, Raised<'src, 'src, BorrowedStatic<'src, i32>>, E>
+ RequestHint<'src, E>,
{
fn upcast_by_id_mut(
&mut self,
id: crate::any::WithLtTypeId<'src>,
) -> Option<crate::any::MutAnyUnsized<'_, 'src>> {
if self
.inner
.as_visitor()
.upcast_by_id_mut(id)
.is_some()
{
trait_by_id!(&mut self, id, {
type Impls = (
dyn Value<'_, OwnedStatic<i32>, E>,
dyn Value<'_, Raised<'_, '_, BorrowedStatic<'_, i32>>, E>,
dyn RequestHint<'_, E>,
);
});
println!("Unknown protocol for Tracer: {:?}", id);
self.inner
.as_visitor()
.into_inner()
.as_any_trait_mut()
.upcast_by_id_mut(id)
} else {
println!("Unknown protocol for builder: {:?}", id);
None
}
}
}
impl<'src, B, E: Environment> Value<'src, OwnedStatic<i32>, E> for Tracer<B, E>
where
B: AsVisitor<'src, E> + DynBind<E>,
{
fn visit<'r>(
&'r mut self,
value: OwnedStatic<i32>,
) -> Canonical<'r, VisitResult<OwnedStatic<i32>>, E>
where
'src: 'r,
Lowered<'r, 'src, OwnedStatic<i32>>: Sized + DynBind<E>,
{
println!("Visited i32: {}", value.0);
visit_value(self.inner.as_visitor(), value)
}
}
impl<'src, B, E: Environment> Value<'src, Raised<'src, 'src, BorrowedStatic<'src, i32>>, E>
for Tracer<B, E>
where
B: AsVisitor<'src, E> + DynBind<E>,
{
fn visit<'r>(
&'r mut self,
value: BorrowedStatic<'src, i32>,
) -> Canonical<'r, VisitResult<BorrowedStatic<'src, i32>>, E>
where
'src: 'r,
Lowered<'r, 'src, OwnedStatic<i32>>: Sized + DynBind<E>,
{
println!("Visited 'src borrow of i32: {}", value.0);
visit_value(self.inner.as_visitor(), value)
}
}
impl<'src, B, E: Environment> RequestHint<'src, E>
for Tracer<B, E>
where
B: AsVisitor<'src, E> + DynBind<E>,
{
fn request_hint<'r>(
&'r mut self,
walker: DynWalker<'r, 'src, E>,
) -> Canonical<'r, VisitResult, E> {
println!("Walker requested hint");
let walker = WalkerTracer::<E> { inner: walker };
E::value((self, walker)).update_map((), |_, (this, walker)| {
request_hint(this.inner.as_visitor(), DynWalker::new(walker)).map((), |_, x| x.unit_skipped()).cast()
}).map((), |_, (_, result)| result).cast()
}
}
#[derive(SendSync)]
struct WalkerTracer<'r, 'src, E: Environment> {
inner: DynWalker<'r, 'src, E>,
}
impl<'r, 'src, E: Environment> AnyTrait<'src> for WalkerTracer<'r, 'src, E>
{
fn upcast_by_id_mut(
&mut self,
id: crate::any::WithLtTypeId<'src>,
) -> Option<crate::any::MutAnyUnsized<'_, 'src>> {
if self
.inner
.upcast_by_id_mut(id)
.is_some()
{
trait_by_id!(&mut self, id, {
type Impls = (
);
});
println!("Unknown walker protocol for Tracer: {:?}", id);
self.inner
.upcast_by_id_mut(id)
} else {
println!("Unknown protocol for walker: {:?}", id);
None
}
}
}