api-macro: support renamed struct fields

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-01-08 10:06:48 +01:00
parent 2e63bf8422
commit 7c6ebbdbf3
3 changed files with 29 additions and 11 deletions

View File

@ -8,7 +8,7 @@ use syn::punctuated::Punctuated;
use syn::Token; use syn::Token;
use super::Schema; use super::Schema;
use crate::serde::{self, SerdeAttrib}; use crate::serde;
use crate::util::{self, FieldName, JSONObject, JSONValue}; use crate::util::{self, FieldName, JSONObject, JSONValue};
/// 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.
@ -51,7 +51,7 @@ 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 attrs = SerdeAttrib::try_from(&variant.attrs[..])?; let attrs = serde::SerdeAttrib::try_from(&variant.attrs[..])?;
if let Some(renamed) = attrs.rename { if let Some(renamed) = attrs.rename {
variants.push(renamed.into_lit_str()); variants.push(renamed.into_lit_str());
} else if let Some(rename_all) = container_attrs.rename_all { } else if let Some(rename_all) = container_attrs.rename_all {

View File

@ -1,5 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryInto; use std::convert::{TryFrom, TryInto};
use failure::Error; use failure::Error;
@ -8,6 +8,7 @@ use quote::quote_spanned;
use super::Schema; use super::Schema;
use crate::api; use crate::api;
use crate::serde;
use crate::util::{self, FieldName, JSONObject}; use crate::util::{self, FieldName, JSONObject};
pub fn handle_struct(attribs: JSONObject, mut stru: syn::ItemStruct) -> Result<TokenStream, Error> { pub fn handle_struct(attribs: JSONObject, mut stru: syn::ItemStruct) -> Result<TokenStream, Error> {
@ -77,22 +78,35 @@ fn handle_regular_struct(
let mut new_fields: Vec<(FieldName, bool, Schema)> = Vec::new(); let mut new_fields: Vec<(FieldName, bool, Schema)> = Vec::new();
let container_attrs = serde::ContainerAttrib::try_from(&stru.attrs[..])?;
if let syn::Fields::Named(ref fields) = &stru.fields { if let syn::Fields::Named(ref fields) = &stru.fields {
for field in &fields.named { for field in &fields.named {
let ident: &Ident = field let attrs = serde::SerdeAttrib::try_from(&field.attrs[..])?;
.ident
.as_ref()
.ok_or_else(|| format_err!(field => "field without name?"))?;
let ident_name: String = ident.to_string(); let (name, span) = {
let ident: &Ident = field
.ident
.as_ref()
.ok_or_else(|| format_err!(field => "field without name?"))?;
match schema_fields.remove(&ident_name) { if let Some(renamed) = attrs.rename {
(renamed.into_str(), ident.span())
} else if let Some(rename_all) = container_attrs.rename_all {
let name = rename_all.apply_to_field(&ident.to_string());
(name, ident.span())
} else {
(ident.to_string(), ident.span())
}
};
match schema_fields.remove(&name) {
Some(field_def) => handle_regular_field(field_def, field, false)?, Some(field_def) => handle_regular_field(field_def, field, false)?,
None => { None => {
let mut field_def = ( let mut field_def = (
FieldName::new(ident_name.clone(), ident.span()), FieldName::new(name.clone(), span),
false, false,
Schema::blank(ident.span()), Schema::blank(span),
); );
handle_regular_field(&mut field_def, field, true)?; handle_regular_field(&mut field_def, field, true)?;
new_fields.push(field_def); new_fields.push(field_def);

View File

@ -70,6 +70,10 @@ impl FieldName {
pub fn into_lit_str(self) -> syn::LitStr { pub fn into_lit_str(self) -> syn::LitStr {
syn::LitStr::new(&self.string, self.ident.span()) syn::LitStr::new(&self.string, self.ident.span())
} }
pub fn into_str(self) -> String {
self.string
}
} }
impl Eq for FieldName {} impl Eq for FieldName {}