ice_rs/slice/
types.rs

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() // All the captured groups
43                .skip(1) // Skipping the complete match
44                .flat_map(|c| c) // Ignoring all empty optional matches
45                .map(|c| c.as_str()) // Grab the original strings
46                .collect::<Vec<_>>() // Create a vector
47        });
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}