apollo-configuration-macros 0.1.1

Supporting macros for apollo-configuration (internal, do not use directly)
Documentation
mod enums;
mod structs;

pub(crate) use enums::ConfigEnumDefinition;
pub(crate) use enums::VariantDefinition;
pub(crate) use enums::VariantFields;
use quote::ToTokens;
use quote::quote;
pub(crate) use structs::ConfigStructDefinition;

#[derive(Clone)]
pub(crate) enum DefaultValue {
    Value(syn::Expr),
    Default,
}

impl ToTokens for DefaultValue {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        match self {
            Self::Default => tokens.extend(quote! { Default::default() }),
            Self::Value(expr) => tokens.extend(expr.to_token_stream()),
        }
    }
}

pub(crate) enum FieldValidator {
    /// This field is not validated. Note it must still pass JSON Schema validation and be able to
    /// be deserialized into the field's type.
    Skip,
    /// Path to a validation function.
    Custom(syn::Path),
}

/// A (named) field within a configuration structure or enum struct variant.
pub(crate) struct FieldDefinition {
    pub(crate) name: syn::Ident,

    pub(crate) ty: syn::Type,

    pub(crate) vis: syn::Visibility,

    /// Non-apollo-configuration field attributes to pass through to the output.
    pub(crate) attrs: Vec<syn::Attribute>,

    /// `#[cfg(...)]` attributes that should be applied to generated code for this field.
    pub(crate) cfg_attrs: Vec<syn::Attribute>,

    /// `Some(required)` if the field is marked as required.
    ///
    /// The identifier is provided to propagate source spans.
    pub(crate) required: Option<syn::Ident>,

    /// The configured default for the field. `None` does _not_ mean that there is no default, as
    /// there is a default...by default; it just means that one wasn't explicitly set.
    ///
    /// Use the `default_value()` method to get the _actual_ default.
    pub(crate) default_value: Option<DefaultValue>,

    /// Field validation override; if `None`, the field should be
    /// validated using the `apollo_configuration::Validate` trait.
    pub(crate) validator: Option<FieldValidator>,

    /// Field attributes to pass through to `schemars`.
    pub(crate) schemars_attrs: Vec<proc_macro2::TokenStream>,
}

impl FieldDefinition {
    /// Returns the default value if one is configured; else returns the default default value if
    /// the field is not marked as required; else returns `None`.
    pub(crate) fn default_value(&self) -> Option<DefaultValue> {
        self.default_value
            .clone()
            .or_else(|| self.required.is_none().then_some(DefaultValue::Default))
    }
}