cgp_field/traits/
transform_map.rs1use core::marker::PhantomData;
2
3use crate::impls::IsNothing;
4use crate::traits::{HasFields, MapType, PartialData, UpdateField};
5use crate::types::{Cons, Field, Nil};
6
7pub trait TransformMap<M1: MapType, M2: MapType, T> {
9 fn transform_mapped(value: M1::Map<T>) -> M2::Map<T>;
10}
11
12pub trait TransformMapFields<Transform, TargetMap> {
13 type Output;
14
15 fn transform_map_fields(self) -> Self::Output;
16}
17
18impl<ContextA, ContextB, Transform, TargetMap, Output> TransformMapFields<Transform, TargetMap>
19 for ContextA
20where
21 ContextA: PartialData<Target = ContextB>,
22 ContextB: HasFields,
23 ContextB::Fields: TransformMapFieldsImpl<ContextA, Transform, TargetMap, Output = Output>,
24{
25 type Output = Output;
26
27 fn transform_map_fields(self) -> Self::Output {
28 ContextB::Fields::transform_map_fields(self)
29 }
30}
31
32trait TransformMapFieldsImpl<Context, Transform, TargetMap> {
33 type Output;
34
35 fn transform_map_fields(context: Context) -> Self::Output;
36}
37
38impl<Context, Transform, TargetMap> TransformMapFieldsImpl<Context, Transform, TargetMap> for Nil {
39 type Output = Context;
40
41 fn transform_map_fields(context: Context) -> Self::Output {
42 context
43 }
44}
45
46impl<Tag, Value, Tail, ContextA, ContextB, ContextC, ContextD, Transform, TargetMap, SourceMap>
47 TransformMapFieldsImpl<ContextA, Transform, TargetMap> for Cons<Field<Tag, Value>, Tail>
48where
49 TargetMap: MapType,
50 SourceMap: MapType,
51 Tail: TransformMapFieldsImpl<ContextA, Transform, TargetMap, Output = ContextB>,
52 ContextB: UpdateField<Tag, IsNothing, Value = Value, Mapper = SourceMap, Output = ContextC>,
53 ContextC: UpdateField<Tag, TargetMap, Value = Value, Output = ContextD>,
54 Transform: TransformMap<SourceMap, TargetMap, Value>,
55{
56 type Output = ContextD;
57
58 fn transform_map_fields(context_a: ContextA) -> Self::Output {
59 let context_b = Tail::transform_map_fields(context_a);
60
61 let (value_a, context_c) = context_b.update_field(PhantomData, ());
62 let value_b = Transform::transform_mapped(value_a);
63 let (_, context_d) = context_c.update_field(PhantomData, value_b);
64
65 context_d
66 }
67}