wasm_wrapper_gen_shared/
types.rs

1use std::fmt;
2
3use quote::{ToTokens, Tokens};
4
5use syn;
6
7use MacroError;
8
9#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10pub enum SupportedCopyTy {
11    U8,
12    U16,
13    U32,
14    USize,
15    I8,
16    I16,
17    I32,
18    ISize,
19    F32,
20    F64,
21    Bool,
22}
23
24impl SupportedCopyTy {
25    pub fn new<T: AsRef<str>>(ident: &T) -> Option<Self> {
26        use self::SupportedCopyTy::*;
27        match ident.as_ref() {
28            "u8" => Some(U8),
29            "u16" => Some(U16),
30            "u32" => Some(U32),
31            "usize" => Some(USize),
32            "i8" => Some(I8),
33            "i16" => Some(I16),
34            "i32" => Some(I32),
35            "isize" => Some(ISize),
36            "f32" => Some(F32),
37            "f64" => Some(F64),
38            "bool" => Some(Bool),
39            _ => None,
40        }
41    }
42
43    pub fn size_in_bytes(&self) -> usize {
44        use self::SupportedCopyTy::*;
45        // not using `std::mem::size_of` since that's for the current platform, not wasm.
46        match *self {
47            Bool | U8 => 1,
48            U16 => 2,
49            USize | U32 => 4,
50            I8 => 1,
51            I16 => 2,
52            ISize | I32 => 4,
53            F32 => 4,
54            F64 => 8,
55        }
56    }
57}
58
59impl AsRef<str> for SupportedCopyTy {
60    fn as_ref(&self) -> &str {
61        use self::SupportedCopyTy::*;
62        match *self {
63            U8 => "u8",
64            U16 => "u16",
65            U32 => "u32",
66            USize => "usize",
67            I8 => "i8",
68            I16 => "i16",
69            I32 => "i32",
70            ISize => "isize",
71            F32 => "f32",
72            F64 => "f64",
73            Bool => "bool",
74        }
75    }
76}
77
78impl fmt::Display for SupportedCopyTy {
79    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80        f.write_str(self.as_ref())
81    }
82}
83
84impl ToTokens for SupportedCopyTy {
85    fn to_tokens(&self, tokens: &mut Tokens) {
86        tokens.append(self.as_ref());
87    }
88}
89
90#[derive(Debug, Copy, Clone, PartialEq, Eq)]
91pub enum SupportedArgumentType {
92    // &[u8]
93    IntegerSliceRef(SupportedCopyTy),
94    // &mut [u8]
95    IntegerSliceMutRef(SupportedCopyTy),
96    // Vec<u8>
97    IntegerVec(SupportedCopyTy),
98    // u8, u16, u32, u64, i8, i16, i32, i64, usize, isize,
99    Integer(SupportedCopyTy),
100    // TODO: more types
101}
102
103fn resolve_parens(mut ty: &syn::Ty) -> &syn::Ty {
104    while let syn::Ty::Paren(ref temp) = *ty {
105        ty = temp;
106    }
107    ty
108}
109
110fn is_u8(ty: &syn::Ty) -> bool {
111    let ty = resolve_parens(ty);
112    if let syn::Ty::Path(None, ref path) = *ty {
113        if path.segments.len() <= 1 {
114            if let Some(segment) = path.segments.first() {
115                if segment.ident == "u8" && segment.parameters == syn::PathParameters::none() {
116                    return true;
117                }
118            }
119        }
120    }
121    false
122}
123
124fn as_simple_integer(ty: &syn::Ty) -> Option<SupportedCopyTy> {
125    let ty = resolve_parens(ty);
126    if let syn::Ty::Path(None, ref path) = *ty {
127        if path.segments.len() <= 1 {
128            if let Some(segment) = path.segments.first() {
129                if segment.parameters == syn::PathParameters::none() {
130                    return SupportedCopyTy::new(&segment.ident);
131                }
132            }
133        }
134    }
135    None
136}
137
138fn as_vec_simple_integer_type(ty: &syn::Ty) -> Option<SupportedCopyTy> {
139    let ty = resolve_parens(ty);
140    if let syn::Ty::Path(None, ref path) = *ty {
141        if path.segments.len() <= 1 {
142            if let Some(segment) = path.segments.first() {
143                if segment.ident == "Vec" {
144                    if let syn::PathParameters::AngleBracketed(ref params) = segment.parameters {
145                        if params.lifetimes.is_empty() && params.bindings.is_empty()
146                            && params.types.len() == 1
147                        {
148                            if let Some(single_param_type) = params.types.first() {
149                                return as_simple_integer(single_param_type);
150                            }
151                        }
152                    }
153                }
154            }
155        }
156    }
157    None
158}
159
160impl SupportedArgumentType {
161    pub fn new(ty: &syn::Ty) -> Result<Self, MacroError> {
162        let ty = resolve_parens(ty);
163        if let syn::Ty::Rptr(_, ref slice_ty_mut) = *ty {
164            let slice_ty = resolve_parens(&slice_ty_mut.ty);
165            if let syn::Ty::Slice(ref byte_ty) = *slice_ty {
166                if let Some(inner_ty) = as_simple_integer(byte_ty) {
167                    return Ok(match slice_ty_mut.mutability {
168                        syn::Mutability::Immutable => {
169                            SupportedArgumentType::IntegerSliceRef(inner_ty)
170                        }
171                        syn::Mutability::Mutable => {
172                            SupportedArgumentType::IntegerSliceMutRef(inner_ty)
173                        }
174                    });
175                }
176                if is_u8(byte_ty) {}
177            }
178        }
179        if let Some(int_ty) = as_simple_integer(ty) {
180            return Ok(SupportedArgumentType::Integer(int_ty));
181        }
182        if let Some(item_ty) = as_vec_simple_integer_type(ty) {
183            return Ok(SupportedArgumentType::IntegerVec(item_ty));
184        }
185        Err(MacroError::UnhandledArgumentType { ty: ty.clone() })?
186    }
187}
188
189pub enum SupportedRetType {
190    // Vec<u8>
191    IntegerVec(SupportedCopyTy),
192    // u8, u16, u32, u64, i8, i16, i32, i64, usize, isize,
193    Integer(SupportedCopyTy),
194    // ()
195    Unit,
196}
197
198
199impl SupportedRetType {
200    pub fn new(ty: &syn::Ty) -> Result<Self, MacroError> {
201        let ty = resolve_parens(ty);
202        if let Some(int_ty) = as_simple_integer(ty) {
203            return Ok(SupportedRetType::Integer(int_ty));
204        }
205        if let Some(item_ty) = as_vec_simple_integer_type(ty) {
206            return Ok(SupportedRetType::IntegerVec(item_ty));
207        }
208        if let syn::Ty::Tup(ref items) = *ty {
209            if items.is_empty() {
210                return Ok(SupportedRetType::Unit);
211            }
212        }
213        Err(MacroError::UnhandledRetType { ty: ty.clone() })?
214    }
215
216    pub fn unit() -> Self {
217        SupportedRetType::Unit
218    }
219}
220
221impl ToTokens for SupportedRetType {
222    fn to_tokens(&self, tokens: &mut Tokens) {
223        use SupportedRetType::*;
224        match *self {
225            IntegerVec(int_ty) => tokens.append(quote! { Vec<#int_ty> }),
226            Integer(int_ty) => int_ty.to_tokens(tokens),
227            Unit => tokens.append("()"),
228        }
229    }
230}