cgp-field-extra 0.5.0

Context-generic programming field traits
Documentation
use cgp_field::impls::{CanBuildFrom, IsNothing, IsOptional, IsPresent};
use cgp_field::traits::{FinalizeBuild, HasBuilder, TransformMap, TransformMapFields};

pub trait CanBuildWithDefault<Source> {
    fn build_with_default(source: Source) -> Self;
}

pub trait CanFinalizeWithDefault {
    type Output;

    fn finalize_with_default(self) -> Self::Output;
}

impl<Source, Target, Builder> CanBuildWithDefault<Source> for Target
where
    Target: HasBuilder<Builder = Builder>,
    Builder: CanBuildFrom<Source>,
    Builder::Output: CanFinalizeWithDefault<Output = Target>,
{
    fn build_with_default(source: Source) -> Target {
        Target::builder().build_from(source).finalize_with_default()
    }
}

impl<Builder, Output> CanFinalizeWithDefault for Builder
where
    Builder: TransformMapFields<TransformMapDefault, IsPresent>,
    Builder::Output: FinalizeBuild<Target = Output>,
{
    type Output = Output;

    fn finalize_with_default(self) -> Output {
        self.transform_map_fields().finalize_build()
    }
}

pub struct TransformMapDefault;

impl<T> TransformMap<IsPresent, IsPresent, T> for TransformMapDefault {
    fn transform_mapped(value: T) -> T {
        value
    }
}

impl<T: Default> TransformMap<IsNothing, IsPresent, T> for TransformMapDefault {
    fn transform_mapped(_value: ()) -> T {
        T::default()
    }
}

impl<T: Default> TransformMap<IsOptional, IsPresent, T> for TransformMapDefault {
    fn transform_mapped(value: Option<T>) -> T {
        value.unwrap_or_default()
    }
}