concourse_resource_derive/
lib.rs1#![deny(
2 warnings,
3 missing_debug_implementations,
4 missing_copy_implementations,
5 trivial_casts,
6 trivial_numeric_casts,
7 unsafe_code,
8 unstable_features,
9 unused_import_braces,
10 unused_qualifications
11)]
12
13extern crate proc_macro;
21
22use crate::proc_macro::TokenStream;
23use quote::quote;
24
25#[proc_macro_derive(IntoMetadataKV)]
26pub fn metadata_kv_derive(input: TokenStream) -> TokenStream {
27 let ast: syn::DeriveInput = syn::parse(input).unwrap();
30
31 match ast.data {
34 syn::Data::Struct(fields) => impl_metadata_kv(ast.ident, fields),
35 _ => panic!("#[derive(IntoMetadataKV)] is only defined for structs"),
36 }
37}
38
39fn impl_metadata_kv(name: syn::Ident, data_struct: syn::DataStruct) -> TokenStream {
40 let md_fields: Vec<_> = data_struct
41 .fields
42 .iter()
43 .filter_map(|field| field.ident.as_ref())
44 .map(|field_name| {
45 let val = quote! {
46 serde_json::to_string(&self.#field_name).unwrap()
47 };
48 quote! {
49 concourse_resource::internal::KV {
50 name: String::from(stringify!(#field_name)),
51 value: #val.strip_prefix('"')
52 .unwrap_or(&#val)
53 .strip_suffix('"')
54 .unwrap_or(&#val)
55 .to_string()
56 }
57 }
58 })
59 .collect();
60
61 let gen = quote! {
62 impl IntoMetadataKV for #name {
63 fn into_metadata_kv(self) -> Vec<concourse_resource::internal::KV> {
64 vec![#(#md_fields,)*]
67 }
68 }
69 };
70 gen.into()
71}