#[macro_export]
macro_rules! Build {
{
$(#[$($attr:tt)*])*
$vis:vis struct $name:ident {$(
$fvis:vis $field:ident: $type:ty
),* $(,)?}
} => {
#[allow(non_upper_case_globals, non_snake_case, non_camel_case_types)]
const _: () = {
impl<'ctx, M: 'ctx, E: $crate::effect::Effect> $crate::Build<'ctx, M, E> for $name {
type Builder = $crate::builders::core::r#struct::StructBuilder<'ctx, __Info, M, E>;
}
$vis struct Builders<'ctx, M, E: $crate::effect::Effect> {
$($field: <$type as $crate::Build<'ctx, M, E>>::Builder),*
}
#[derive(Copy, Clone, Debug)]
$vis enum Field {
$($field),*
}
mod field_index {
enum __Fields {
$($field),*
}
$(pub const $field: usize = __Fields::$field as usize;)*
}
#[derive(Debug)]
$vis enum Error {
$($field(<$type as $crate::BuilderTypes>::Error)),*
}
impl ::core::fmt::Display for Field {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_str(match self {
$(Field::$field => stringify!($field)),*
})
}
}
impl ::core::fmt::Display for Error {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_str(match self {
$(Error::$field(_) => stringify!($field)),*
})
}
}
$vis struct __Info;
impl<'ctx, M: 'ctx> $crate::builders::core::r#struct::StructTypeInfo<'ctx, M> for __Info {
type Builders<E: $crate::effect::Effect> = Builders<'ctx, M, E>;
type FieldMarker = Field;
type T = $name;
type Error = Error;
type Seed = ($(<$type as $crate::BuilderTypes>::Seed),*);
type ValueT = $crate::any::OwnedStatic<$name>;
const FIELD_COUNT: usize = {
[$(stringify!($field)),*].len()
};
#[inline(always)]
fn new_builders<'a, E: $crate::effect::Effect>(seed: Self::Seed) -> $crate::effect::ErasedEffective<'a, Self::Builders<E>, E> {
let ($($field),*) = seed;
use $crate::effect::EffectiveExt;
$crate::effect::join(
($(<<$type as $crate::Build<'ctx, M, E>>::Builder as $crate::Builder::<E>>::from_seed($field),)*)
).map(|($($field,)*)| {
Builders {
$($field),*
}
})
}
fn from_builders<'a, E: $crate::effect::Effect>(builders: Self::Builders<E>) -> $crate::effect::ErasedEffective<'a, Result<Self::T, Self::Error>, E> {
use $crate::Builder;
use $crate::effect::EffectiveExt;
$crate::effect::try_join(
(
$(|| builders.$field.build().map(|x| x.map_err(Error::$field)),)*
)
).map(|result| match result {
Ok(($($field,)*)) => Ok($name {
$($field),*
}),
Err(err) => Err(err)
})
}
fn as_visitor<'a, E: $crate::effect::Effect>(
marker: Self::FieldMarker,
builders: &'a mut Self::Builders<E>,
) -> $crate::protocol::DynVisitor<'a, 'ctx> {
use $crate::Builder;
match marker {
$(Field::$field => builders.$field.as_visitor()),*
}
}
fn marker_from_index(index: usize) -> Option<Self::FieldMarker> {
match index {
$(field_index::$field => Some(Field::$field),)*
_ => None
}
}
fn marker_from_name(name: &str) -> Option<Self::FieldMarker> {
match name {
$(stringify!($field) => Some(Field::$field),)*
_ => None
}
}
fn from_value(value: Self::ValueT) -> Self::T {
value.0
}
}
};
}
}