in shed/facet/proc_macros/factory_impl.rs [87:214]
fn gen_sync_factory_builder(
facet_crate: &Ident,
factory_ty: &Ident,
builder_ident: &Ident,
params: &Params,
facets: &Facets,
) -> Result<TokenStream, Error> {
let builder_facets_ident = format_ident!("{}BuilderFacets", factory_ty);
let param_idents = ¶ms.param_idents;
let param_types = ¶ms.param_types;
let facet_idents = &facets.facet_idents;
let facet_types = &facets.facet_types;
let facet_types_map = facet_idents
.iter()
.zip(facet_types)
.collect::<BTreeMap<_, _>>();
let mut builder_impls = Vec::new();
for (facet_ident, facet_type, fallibility, asyncness, facet_params) in facets.iter() {
let mut call_params = Vec::new();
let mut make_facets = Vec::new();
for facet_param in facet_params {
match facet_param {
FactoryParam::Facet(ident) => {
let param_type = facet_types_map
.get(ident)
.ok_or_else(|| Error::new(ident.span(), "unrecognised facet name"))?;
make_facets.push(quote! {
let #ident: #param_type = self.build()?;
});
call_params.push(quote!(&#ident));
}
FactoryParam::Param(ident) => {
call_params.push(quote!(&self.facets.#ident));
}
}
}
if asyncness == Asyncness::Asynchronous {
panic!("should not generate sync builder for async factory");
}
let maybe_map_err = fallibility.maybe(quote! {
.map_err(|e| ::#facet_crate::FactoryError::FacetBuildFailed {
name: stringify!(#facet_ident),
source: e.into(),
})?
});
builder_impls.push(quote! {
impl ::#facet_crate::Builder<#facet_type> for #builder_ident<'_> {
fn build<'builder>(&'builder mut self) -> ::std::result::Result<
#facet_type,
::#facet_crate::FactoryError,
> {
if let Some(facet) = self.facets.#facet_ident.as_ref() {
return Ok(facet.clone());
}
use ::#facet_crate::Builder as _;
#( #make_facets )*
let #facet_ident =
self.factory.#facet_ident( #( #call_params ),* )
#maybe_map_err;
debug_assert!(self.facets.#facet_ident.is_none());
self.facets.#facet_ident = Some(#facet_ident.clone());
Ok(#facet_ident)
}
}
})
}
let builder = quote! {
#[doc(hidden)]
pub struct #builder_facets_ident {
#(
#param_idents: #param_types,
)*
#(
#facet_idents: ::std::option::Option<#facet_types>,
)*
}
impl #builder_facets_ident {
#[doc(hidden)]
pub fn new( #( #param_idents: #param_types, )* ) -> Self {
Self {
#( #param_idents, )*
#(
#facet_idents: ::std::default::Default::default(),
)*
}
}
}
#(
#builder_impls
)*
#[doc(hidden)]
pub struct #builder_ident<'factory> {
factory: &'factory #factory_ty,
facets: #builder_facets_ident,
}
impl #factory_ty {
/// Build an instance of a container from this factory.
pub fn build<'factory, T>(
&'factory self,
#( #param_idents: #param_types ),*
) -> ::std::result::Result<T, ::#facet_crate::FactoryError>
where
T: ::#facet_crate::Buildable<#builder_ident<'factory>>,
{
let mut builder = #builder_ident {
factory: &self,
facets: #builder_facets_ident::new(#( #param_idents, )*),
};
T::build(&mut builder)
}
}
};
Ok(builder)
}