1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use crate::primitives::Primitive;
use quote::{quote, ToTokens};
use std::{collections::BTreeMap, hash::Hash};
use syn::Item;
mod cargo_dependency;
mod custom_type;
mod enums;
mod structs;
mod type_ident;
pub use cargo_dependency::CargoDependency;
pub use custom_type::CustomType;
pub use enums::{Enum, EnumOptions, Variant, VariantAttrs};
pub use structs::{Field, FieldAttrs, Struct, StructOptions};
pub use type_ident::TypeIdent;
pub type TypeMap = BTreeMap<TypeIdent, Type>;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Type {
Alias(String, TypeIdent),
Container(String, TypeIdent),
Custom(CustomType),
Enum(Enum),
List(String, TypeIdent),
Map(String, TypeIdent, TypeIdent),
Primitive(Primitive),
String,
Struct(Struct),
Tuple(Vec<TypeIdent>),
Unit,
}
impl Type {
pub fn from_item(item_str: &str) -> Self {
let item = syn::parse_str::<Item>(item_str).unwrap();
match item {
Item::Enum(item) => Type::Enum(enums::parse_enum_item(item)),
Item::Struct(item) => Type::Struct(structs::parse_struct_item(item)),
item => panic!(
"Only struct and enum types can be constructed from an item. Found: {:?}",
item
),
}
}
pub fn name(&self) -> String {
match self {
Self::Alias(name, _) => name.clone(),
Self::Container(name, ident) => format!("{}<{}>", name, ident),
Self::Custom(custom) => custom.ident.to_string(),
Self::Enum(Enum { ident, .. }) => ident.to_string(),
Self::List(name, ident) => format!("{}<{}>", name, ident),
Self::Map(name, key, value) => format!("{}<{}, {}>", name, key, value),
Self::Primitive(primitive) => primitive.name(),
Self::String => "String".to_owned(),
Self::Struct(Struct { ident, .. }) => ident.to_string(),
Self::Tuple(items) => format!(
"({})",
items
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ")
),
Self::Unit => "()".to_owned(),
}
}
}
impl ToTokens for Type {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
(match self {
Type::Alias(name, _) | Type::Custom(CustomType { rs_ty: name, .. }) => {
let ty = syn::parse_str::<syn::Type>(name).unwrap();
quote! { #ty }
}
Type::Container(name, ident) | Type::List(name, ident) => {
let name = syn::parse_str::<syn::Type>(name).unwrap();
quote! { #name<#ident> }
}
Type::Struct(Struct { ident, .. }) | Type::Enum(Enum { ident, .. }) => {
quote! { #ident }
}
Type::Map(name, k, v) => {
let name = syn::parse_str::<syn::Type>(name).unwrap();
quote! { #name<#k, #v> }
}
Type::Primitive(primitive) => quote! { #primitive },
Type::String => quote! { String },
Type::Tuple(items) => quote! { (#(#items),*) },
Type::Unit => quote! { () },
})
.to_tokens(tokens)
}
}