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
use super::{builtin_type_ext::BuiltinTypeExt, to_ident::ToIdent};
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use std::rc::Rc;
use witx::{BuiltinType, NamedType, Type, TypeRef};

pub(crate) trait TypeRefExt {
    fn to_type(&self) -> TokenStream;
    fn get_type_definition(&self) -> &Rc<Type>;
    fn is_string(&self) -> bool;
    fn as_array(&self) -> Option<&Rc<NamedType>>;
}

impl TypeRefExt for TypeRef {
    fn to_type(&self) -> TokenStream {
        match self {
            TypeRef::Name(ref named_type) => {
                named_type.name.to_ident_native(None).to_token_stream()
            }
            TypeRef::Value(ref value) => match **value {
                Type::Builtin(builtin) => builtin.to_inner(),
                Type::Pointer(ref pointee) | Type::ConstPointer(ref pointee) => {
                    let pointee_name = pointee.to_type();
                    quote! { witx_gen::WasmSlicePtr<#pointee_name> }
                }
                _ => panic!("Could not determine type name for {:?}.", self),
            },
        }
    }

    fn get_type_definition(&self) -> &Rc<Type> {
        match self {
            TypeRef::Name(ref named_type) => named_type.tref.get_type_definition(),
            TypeRef::Value(ref tp) => tp,
        }
    }

    fn is_string(&self) -> bool {
        if let TypeRef::Value(ref tp) = self {
            if let Type::Builtin(ref builtin_type) = **tp {
                if let BuiltinType::String = builtin_type {
                    return true;
                }
            }
        }

        false
    }

    fn as_array(&self) -> Option<&Rc<NamedType>> {
        if let witx::TypeRef::Name(ref named) = self {
            if let witx::TypeRef::Value(ref tp) = named.tref {
                if let witx::Type::Array(ref inner) = **tp {
                    if let witx::TypeRef::Name(ref inner_named) = inner {
                        return Some(inner_named);
                    }
                }
            }
        }

        None
    }
}