-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathenums.rs
115 lines (104 loc) · 3.56 KB
/
enums.rs
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::types::RustType;
use askama::Template;
use syn::{Expr, Fields, ItemEnum, Lit};
#[derive(Clone, Debug)]
pub enum EnumVariantDeclaration {
Unit {
ident: String,
value: String,
},
Unnamed {
ident: String,
types: Vec<RustType>,
},
Named {
ident: String,
types: Vec<(String, RustType)>,
},
}
impl EnumVariantDeclaration {
pub fn ident(&self) -> String {
match self {
EnumVariantDeclaration::Unit { ident, .. } => ident.to_string(),
EnumVariantDeclaration::Unnamed { ident, .. } => ident.to_string(),
EnumVariantDeclaration::Named { ident, .. } => ident.to_string(),
}
}
pub fn value(&self) -> String {
match self {
EnumVariantDeclaration::Unit { value, .. } => value.to_string(),
_ => panic!("should not happen"),
}
}
pub fn first_type(&self) -> RustType {
match self {
EnumVariantDeclaration::Unnamed { types, .. } => types[0].clone(),
_ => panic!("should not happen"),
}
}
}
#[derive(Clone, Debug, Template)]
#[template(path = "enum.ts.j2", escape = "txt")]
pub struct EnumDeclaration {
ident: String,
variants: Vec<EnumVariantDeclaration>,
}
impl EnumDeclaration {
pub fn new(ident: String) -> Self {
EnumDeclaration {
ident,
variants: Default::default(),
}
}
pub fn is_unit(&self) -> bool {
self.variants
.iter()
.all(|v| matches!(v, EnumVariantDeclaration::Unit { .. }))
}
}
impl From<ItemEnum> for EnumDeclaration {
fn from(node: ItemEnum) -> Self {
let mut e = EnumDeclaration::new(node.ident.to_string());
for (i, variant) in node.variants.into_iter().enumerate() {
match variant.fields {
Fields::Unit => {
let value = if let Some(discriminant) = variant.discriminant {
if let Expr::Lit(lit) = discriminant.1 {
if let Lit::Int(val) = lit.lit {
Some(val.to_string())
} else {
None
}
} else {
None
}
} else {
None
};
e.variants.push(EnumVariantDeclaration::Unit {
ident: variant.ident.to_string(),
value: value.unwrap_or_else(|| i.to_string()),
})
}
Fields::Named(fields) => e.variants.push(EnumVariantDeclaration::Named {
ident: variant.ident.to_string(),
types: fields
.named
.into_iter()
.map(|v| {
(
v.ident.expect("Should have an ident").to_string(),
v.ty.into(),
)
})
.collect(),
}),
Fields::Unnamed(fields) => e.variants.push(EnumVariantDeclaration::Unnamed {
ident: variant.ident.to_string(),
types: fields.unnamed.into_iter().map(|v| v.ty.into()).collect(),
}),
}
}
e
}
}