use crate::fields::Ast;
use syn::{Fields, FieldsNamed, Generics, Ident};
pub(crate) struct Model {
pub ident: Ident,
pub generics: Generics,
pub fields: Vec<String>,
}
pub(crate) fn analyze(ast: Ast) -> Model {
let fields = match ast.fields {
Fields::Named(FieldsNamed { ref named, .. }) => named
.iter()
.filter_map(|f| f.ident.clone().map(|ident| ident.to_string()))
.collect::<Vec<_>>(),
_ => vec![],
};
Model {
ident: ast.ident,
generics: ast.generics,
fields,
}
}
#[cfg(test)]
mod tests {
use syn::parse_quote;
use super::*;
#[test]
fn can_get_fields_from_nonempty_named_struct() {
let model = analyze(parse_quote!(
struct NamedStruct {
first: u64,
second: String,
third: Vec<char>,
}
));
let expected: Vec<_> = ["first", "second", "third"]
.iter()
.map(|s| s.to_owned())
.collect();
assert_eq!("NamedStruct", model.ident.to_string());
assert!(model.generics.type_params().next().is_none());
assert!(model.generics.const_params().next().is_none());
assert_eq!(expected, model.fields);
}
#[test]
fn can_get_fields_from_generic_named_struct() {
let model = analyze(parse_quote!(
struct GenericStruct<'a, T, E, S, const N: usize> {
value: T + 'a,
error: E,
size: S,
}
));
let expected: Vec<_> = ["value", "error", "size"]
.iter()
.map(|s| s.to_owned())
.collect();
assert_eq!("GenericStruct", model.ident.to_string());
assert_eq!(model.generics.type_params().count(), 3);
assert_eq!(model.generics.const_params().count(), 1);
assert_eq!(expected, model.fields);
}
#[test]
fn can_get_fields_from_empty_named_struct() {
let model = analyze(parse_quote!(
struct EmptyNamedStruct {}
));
assert_eq!("EmptyNamedStruct", model.ident.to_string());
assert!(model.generics.type_params().next().is_none());
assert!(model.generics.const_params().next().is_none());
assert!(model.fields.is_empty());
}
#[test]
fn can_get_fields_from_empty_unnamed_struct() {
let model = analyze(parse_quote!(
struct UnnamedStruct();
));
assert_eq!("UnnamedStruct", model.ident.to_string());
assert!(model.generics.type_params().next().is_none());
assert!(model.generics.const_params().next().is_none());
assert!(model.fields.is_empty());
}
#[test]
fn can_get_fields_from_unit_struct() {
let model = analyze(parse_quote!(
struct UnitStruct;
));
assert_eq!("UnitStruct", model.ident.to_string());
assert!(model.generics.type_params().next().is_none());
assert!(model.generics.const_params().next().is_none());
assert!(model.fields.is_empty());
}
}