1use syn::{PathArguments, Type};
2
3pub(crate) use crate::named_field::StructField;
4
5#[derive(PartialEq, Debug, Clone)]
6pub(crate) enum Shape {
7 Optional(Type),
9 Multiple(Type),
11 Bool,
13 Unit,
15 Direct(Type),
17}
18
19pub(crate) fn split_type(ty: &Type) -> Shape {
20 fn single_arg(x: &PathArguments) -> Option<Type> {
21 match x {
22 PathArguments::AngleBracketed(arg) => {
23 if arg.args.len() == 1 {
24 match &arg.args[0] {
25 syn::GenericArgument::Type(ty) => Some(ty.clone()),
26 _ => None,
27 }
28 } else {
29 None
30 }
31 }
32 PathArguments::None | PathArguments::Parenthesized(_) => None,
33 }
34 }
35
36 fn try_split_type(ty: &Type) -> Option<Shape> {
37 if let Type::Tuple(syn::TypeTuple { elems, .. }) = ty {
38 if elems.is_empty() {
39 return Some(Shape::Unit);
40 }
41 }
42
43 let last = match ty {
44 Type::Path(p) => p.path.segments.last()?,
45 _ => return None,
46 };
47 if last.ident == "Vec" {
48 Some(Shape::Multiple(single_arg(&last.arguments)?))
49 } else if last.ident == "Option" {
50 Some(Shape::Optional(single_arg(&last.arguments)?))
51 } else if last.ident == "bool" {
52 Some(Shape::Bool)
53 } else {
54 None
55 }
56 }
57 try_split_type(ty).unwrap_or_else(|| Shape::Direct(ty.clone()))
58}