#![allow(clippy::manual_unwrap_or_default)]
use darling::{FromDeriveInput, FromMeta};
use syn::{Data, DeriveInput, Path, parse_quote};
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(resource))]
struct InheritAttrs {
inherit: syn::Path,
#[darling(default)]
crates: Crates,
}
#[derive(Debug, FromMeta)]
struct Crates {
#[darling(default = "Self::default_kube_core")]
kube_core: Path,
#[darling(default = "Self::default_k8s_openapi")]
k8s_openapi: Path,
}
impl Default for Crates {
fn default() -> Self {
Self::from_list(&[]).unwrap()
}
}
impl Crates {
fn default_kube_core() -> Path {
parse_quote! { ::kube::core } }
fn default_k8s_openapi() -> Path {
parse_quote! { ::k8s_openapi }
}
}
pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
let derive_input: DeriveInput = match syn::parse2(input) {
Err(err) => return err.to_compile_error(),
Ok(di) => di,
};
match derive_input.data {
Data::Struct(_) | Data::Enum(_) => {}
_ => {
return syn::Error::new_spanned(&derive_input.ident, r#"Unions can not #[derive(Resource)]"#)
.to_compile_error();
}
}
let kube_attrs = match InheritAttrs::from_derive_input(&derive_input) {
Err(err) => return err.write_errors(),
Ok(attrs) => attrs,
};
let InheritAttrs {
inherit: resource,
crates: Crates {
kube_core,
k8s_openapi,
},
..
} = kube_attrs;
let rootident = derive_input.ident;
let inherit_resource = quote! {
impl #kube_core::Resource for #rootident {
type DynamicType = <#resource as #kube_core::Resource>::DynamicType;
type Scope = <#resource as #kube_core::Resource>::Scope;
fn group(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
#resource::group(&Default::default()).into_owned().into()
}
fn kind(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
#resource::kind(&Default::default()).into_owned().into()
}
fn version(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
#resource::version(&Default::default()).into_owned().into()
}
fn api_version(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
#resource::api_version(&Default::default()).into_owned().into()
}
fn plural(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
#resource::plural(&Default::default()).into_owned().into()
}
fn meta(&self) -> &#k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
&self.metadata
}
fn meta_mut(&mut self) -> &mut #k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
&mut self.metadata
}
}
};
quote! {
#inherit_resource
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_inherit() {
let input = quote! {
#[derive(Resource)]
#[resource(inherit = "ConfigMap")]
struct Foo { metadata: ObjectMeta }
};
let input = syn::parse2(input).unwrap();
InheritAttrs::from_derive_input(&input).unwrap();
}
}