cgp_field/impls/
build_from.rs

1use core::marker::PhantomData;
2
3use crate::traits::{BuildField, HasFields, IntoBuilder, TakeField};
4use crate::types::{Cons, Field, Nil};
5
6pub trait CanBuildFrom<Source> {
7    type Output;
8
9    fn build_from(self, source: Source) -> Self::Output;
10}
11
12impl<Builder, Source, Output> CanBuildFrom<Source> for Builder
13where
14    Source: HasFields + IntoBuilder,
15    Source::Fields: FieldsBuilder<Source::Builder, Builder, Output = Output>,
16{
17    type Output = Output;
18
19    fn build_from(self, source: Source) -> Output {
20        Source::Fields::build_fields(source.into_builder(), self)
21    }
22}
23
24trait FieldsBuilder<Source, Target> {
25    type Output;
26
27    fn build_fields(source: Source, target: Target) -> Self::Output;
28}
29
30impl<Source, Target, RestFields, Tag, Value> FieldsBuilder<Source, Target>
31    for Cons<Field<Tag, Value>, RestFields>
32where
33    Source: TakeField<Tag, Value = Value>,
34    Target: BuildField<Tag, Value = Value>,
35    RestFields: FieldsBuilder<Source::Remainder, Target::Output>,
36{
37    type Output = RestFields::Output;
38
39    fn build_fields(source: Source, target: Target) -> Self::Output {
40        let (value, next_source) = source.take_field(PhantomData);
41        let next_target = target.build_field(PhantomData, value);
42
43        RestFields::build_fields(next_source, next_target)
44    }
45}
46
47impl<Source, Target> FieldsBuilder<Source, Target> for Nil {
48    type Output = Target;
49
50    fn build_fields(_source: Source, target: Target) -> Self::Output {
51        target
52    }
53}