api-macro: start using serde attribute helpers

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-01-07 15:23:52 +01:00
parent 799c993d63
commit dd5cd3f311
3 changed files with 12 additions and 45 deletions

View File

@ -1,32 +1,16 @@
use std::convert::TryInto; use std::convert::{TryFrom, TryInto};
use failure::Error; use failure::Error;
use proc_macro2::{Ident, Span, TokenStream}; use proc_macro2::{Ident, Span, TokenStream};
use quote::quote_spanned; use quote::quote_spanned;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated; use syn::punctuated::Punctuated;
use syn::Token; use syn::Token;
use super::Schema; use super::Schema;
use crate::serde::SerdeAttrib;
use crate::util::{self, FieldName, JSONObject, JSONValue}; use crate::util::{self, FieldName, JSONObject, JSONValue};
/// `parse_macro_input!` expects a TokenStream_1
struct AttrArgs {
_paren_token: syn::token::Paren,
args: Punctuated<syn::NestedMeta, Token![,]>,
}
impl Parse for AttrArgs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let content;
Ok(Self {
_paren_token: syn::parenthesized!(content in input),
args: Punctuated::parse_terminated(&content)?,
})
}
}
/// Enums, provided they're simple enums, simply get an enum string schema attached to them. /// Enums, provided they're simple enums, simply get an enum string schema attached to them.
pub fn handle_enum( pub fn handle_enum(
mut attribs: JSONObject, mut attribs: JSONObject,
@ -65,27 +49,10 @@ pub fn handle_enum(
_ => bail!(variant => "api macro does not support enums with fields"), _ => bail!(variant => "api macro does not support enums with fields"),
} }
let mut renamed = false; let attrs = SerdeAttrib::try_from(&variant.attrs[..])?;
for attrib in &variant.attrs { if let Some(renamed) = attrs.rename {
if !attrib.path.is_ident("serde") { variants.push(renamed.into_lit_str());
continue; } else {
}
let args: AttrArgs = syn::parse2(attrib.tokens.clone())?;
for arg in args.args {
if let syn::NestedMeta::Meta(syn::Meta::NameValue(var)) = arg {
if var.path.is_ident("rename") {
match var.lit {
syn::Lit::Str(lit) => variants.push(lit),
_ => bail!(var.lit => "'rename' value must be a string literal"),
}
renamed = true;
}
}
}
}
if !renamed {
let name = &variant.ident; let name = &variant.ident;
variants.push(syn::LitStr::new(&name.to_string(), name.span())); variants.push(syn::LitStr::new(&name.to_string(), name.span()));
} }

View File

@ -5,10 +5,6 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::Token;
use crate::util::{AttrArgs, FieldName}; use crate::util::{AttrArgs, FieldName};
/// Serde name types. /// Serde name types.
@ -127,7 +123,7 @@ impl RenameAll {
/// `serde` container attributes we support /// `serde` container attributes we support
#[derive(Default)] #[derive(Default)]
pub struct ContainerAttrib { pub struct ContainerAttrib {
rename_all: Option<RenameAll>, pub rename_all: Option<RenameAll>,
} }
impl TryFrom<&[syn::Attribute]> for ContainerAttrib { impl TryFrom<&[syn::Attribute]> for ContainerAttrib {
@ -162,7 +158,7 @@ impl TryFrom<&[syn::Attribute]> for ContainerAttrib {
/// `serde` field/variant attributes we support /// `serde` field/variant attributes we support
#[derive(Default)] #[derive(Default)]
pub struct SerdeAttrib { pub struct SerdeAttrib {
rename: Option<FieldName>, pub rename: Option<FieldName>,
} }
impl TryFrom<&[syn::Attribute]> for SerdeAttrib { impl TryFrom<&[syn::Attribute]> for SerdeAttrib {

View File

@ -66,6 +66,10 @@ impl FieldName {
pub fn cmp(&self, other: &Self) -> std::cmp::Ordering { pub fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.string.cmp(&other.string) self.string.cmp(&other.string)
} }
pub fn into_lit_str(self) -> syn::LitStr {
syn::LitStr::new(&self.string, self.ident.span())
}
} }
impl Eq for FieldName {} impl Eq for FieldName {}