mirror of
https://github.com/OMGeeky/confique.git
synced 2026-01-02 01:26:28 +01:00
Regarding nested fields: I cannot imagine a situation where that distinction is useful. Also, specifying an empty nested object looks stupid in TOML and YAML anyway. Regarding default fields: If there is a default value, then the field should not be declared as optional to begin with.
47 lines
1.3 KiB
Rust
47 lines
1.3 KiB
Rust
|
|
/// Checks if the given type is an `Option` and if so, return the inner type.
|
|
///
|
|
/// Note: this function clearly shows one of the major shortcomings of proc
|
|
/// macros right now: we do not have access to the compiler's type tables and
|
|
/// can only check if it "looks" like an `Option`. Of course, stuff can go
|
|
/// wrong. But that's the best we can do and it's highly unlikely that someone
|
|
/// shadows `Option`.
|
|
pub(crate) fn unwrap_option(ty: &syn::Type) -> Option<&syn::Type> {
|
|
let ty = match ty {
|
|
syn::Type::Path(path) => path,
|
|
_ => return None,
|
|
};
|
|
|
|
if ty.qself.is_some() || ty.path.leading_colon.is_some() {
|
|
return None;
|
|
}
|
|
|
|
let valid_paths = [
|
|
&["Option"] as &[_],
|
|
&["std", "option", "Option"],
|
|
&["core", "option", "Option"],
|
|
];
|
|
if !valid_paths.iter().any(|vp| ty.path.segments.iter().map(|s| &s.ident).eq(*vp)) {
|
|
return None;
|
|
}
|
|
|
|
let args = match &ty.path.segments.last().unwrap().arguments {
|
|
syn::PathArguments::AngleBracketed(args) => args,
|
|
_ => return None,
|
|
};
|
|
|
|
if args.args.len() != 1 {
|
|
return None;
|
|
}
|
|
|
|
match &args.args[0] {
|
|
syn::GenericArgument::Type(t) => Some(t),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/// Returns `true` if the given type is `Option<_>`.
|
|
pub(crate) fn is_option(ty: &syn::Type) -> bool {
|
|
unwrap_option(ty).is_some()
|
|
}
|