use crate::{
build::Builder,
effect::{Effect, Future},
hkt::Marker,
Walk, Walker, WalkerTypes,
};
#[inline]
#[allow(clippy::type_complexity)]
pub fn transform<'a, 'ctx, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect>(
seed: B::Seed,
walker: W,
) -> Future<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> {
E::wrap(async {
// Create builder from seed value;
let mut builder = B::from_seed(seed).await;
// Walk the walker with the builder as the visitor.
let walker_result = walker.walk(builder.as_visitor()).await;
// Finish building the value.
let builder_result = builder.build().await;
(builder_result, walker_result)
})
}
/// For use in a lens.
pub struct Projection<T, B, U, M> {
value: T,
builder: B,
_marker: Marker<(U, M)>,
}
#[allow(clippy::type_complexity)]
impl<T, B, U: Send + Sync, M> Projection<T, B, U, M> {
pub fn project_ref<'a, E: Effect>(
&'a self,
) -> Future<
'a,
(
Result<&'a U, B::Error>,
Result<<&'a T as WalkerTypes>::Output, <&'a T as WalkerTypes>::Error>,
),
E,
>
where
&'a T: Walk<'a, M, E>,
B: Clone + Builder<'a, E, Value = &'a U>,
{
let walker = self.value.into_walker();
let mut builder = self.builder.clone();
E::wrap(async {
let result = walker.walk(builder.as_visitor()).await;
(builder.build().await, result)
})
}
pub fn project_mut<'a, E: Effect>(
&'a mut self,
) -> Future<
'a,
(
Result<&'a mut U, B::Error>,
Result<<&'a mut T as WalkerTypes>::Output, <&'a mut T as WalkerTypes>::Error>,
),
E,
>
where
&'a mut T: Walk<'a, M, E>,
B: Clone + Builder<'a, E, Value = &'a mut U>,
{
let walker = self.value.into_walker();
let mut builder = self.builder.clone();
E::wrap(async {
let result = walker.walk(builder.as_visitor()).await;
(builder.build().await, result)
})
}
pub fn project<'a, E: Effect>(
self,
) -> Future<
'a,
(
Result<U, B::Error>,
Result<<T as WalkerTypes>::Output, <T as WalkerTypes>::Error>,
),
E,
>
where
T: Walk<'a, M, E> + 'a,
M: 'a,
B: Clone + Builder<'a, E, Value = U> + 'a,
{
let walker = self.value.into_walker();
let mut builder = self.builder.clone();
E::wrap(async {
let result = walker.walk(builder.as_visitor()).await;
(builder.build().await, result)
})
}
}