1use quote::__private::TokenStream;
2use quote::*;
3use regex::Regex;
4
5#[derive(Clone, Debug)]
6pub enum IceType {
7 VoidType,
8 BoolType,
9 ByteType,
10 ShortType,
11 IntType,
12 LongType,
13 FloatType,
14 DoubleType,
15 StringType,
16 SequenceType(Box<IceType>),
17 DictType(Box<IceType>, Box<IceType>),
18 Optional(Box<IceType>, u8),
19 CustomType(String)
20}
21
22impl IceType {
23 pub fn from(text: &str) -> Result<IceType, Box<dyn std::error::Error>> {
24 let type_re = Regex::new(
25 r#"(?x)
26 (void) |
27 (bool) |
28 (byte) |
29 (short) |
30 (int) |
31 (long) |
32 (float) |
33 (double) |
34 (string) |
35 (sequence)<(.+)> |
36 (dictionary)<(.+),\s*(.+)> |
37 "#
38 )?;
39
40 let captures = type_re.captures(text.trim()).map(|captures| {
41 captures
42 .iter() .skip(1) .flat_map(|c| c) .map(|c| c.as_str()) .collect::<Vec<_>>() });
48
49 match captures.as_ref().map(|c| c.as_slice()) {
50 Some(["void"]) => Ok(IceType::VoidType),
51 Some(["bool"]) => Ok(IceType::BoolType),
52 Some(["byte"]) => Ok(IceType::ByteType),
53 Some(["short"]) => Ok(IceType::ShortType),
54 Some(["int"]) => Ok(IceType::IntType),
55 Some(["long"]) => Ok(IceType::LongType),
56 Some(["float"]) => Ok(IceType::FloatType),
57 Some(["double"]) => Ok(IceType::DoubleType),
58 Some(["string"]) => Ok(IceType::StringType),
59 Some(["sequence", x]) => {
60 Ok(IceType::SequenceType(Box::new(IceType::from(x)?)))
61 },
62 Some(["dictionary", x, y]) => {
63 Ok(IceType::DictType(Box::new(IceType::from(x)?), Box::new(IceType::from(y)?)))
64 },
65 _ => Ok(IceType::CustomType(text.trim().to_string()))
66 }
67 }
68
69 pub fn rust_type(&self) -> String {
70 match self {
71 IceType::VoidType => String::from("()"),
72 IceType::BoolType => String::from("bool"),
73 IceType::ByteType => String::from("u8"),
74 IceType::ShortType => String::from("i16"),
75 IceType::IntType => String::from("i32"),
76 IceType::LongType => String::from("i64"),
77 IceType::FloatType => String::from("f32"),
78 IceType::DoubleType => String::from("f64"),
79 IceType::StringType => String::from("String"),
80 IceType::SequenceType(type_name) => format!("Vec<{}>", type_name.rust_type()),
81 IceType::DictType(key_type, value_type) => format!("HashMap<{}, {}>", key_type.rust_type(), value_type.rust_type()),
82 IceType::Optional(type_name, _) => format!("Option<{}>", type_name.rust_type()),
83 IceType::CustomType(type_name) => format!("{}", type_name),
84 }
85 }
86
87 pub fn token_from(&self) -> TokenStream {
88 match self {
89 IceType::Optional(type_name, _) => {
90 let sub_type = type_name.token();
91 quote!{ Option::<#sub_type> }
92 }
93 _ => self.token(),
94 }
95 }
96
97 pub fn token(&self) -> TokenStream {
98 match self {
99 IceType::VoidType => quote! { () },
100 IceType::BoolType => quote! { bool },
101 IceType::ByteType => quote! { u8 },
102 IceType::ShortType => quote! { i16 },
103 IceType::IntType => quote! { i32 },
104 IceType::LongType => quote! { i64 },
105 IceType::FloatType => quote! { f32 },
106 IceType::DoubleType => quote! { f64 },
107 IceType::StringType => quote! { String },
108 IceType::SequenceType(type_name) => {
109 let sub_type = type_name.token();
110 quote!{ Vec<#sub_type> }
111 },
112 IceType::DictType(key_type, value_type) => {
113 let key = key_type.token();
114 let value = value_type.token();
115 quote!{ HashMap<#key, #value> }
116 },
117 IceType::Optional(type_name, _) => {
118 let sub_type = type_name.token();
119 quote!{ Option<#sub_type> }
120 },
121 IceType::CustomType(type_name) => {
122 let id = format_ident!("{}", type_name);
123 quote!{ #id }
124 },
125 }
126 }
127
128 pub fn as_ref(&self) -> bool {
129 match self {
130 IceType::StringType |
131 IceType::SequenceType(_) |
132 IceType::DictType(_, _) |
133 IceType::CustomType(_) => true,
134 _ => false
135 }
136 }
137}