webwire_cli/schema/
type.rs

1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::rc::{Rc, Weak};
4
5use crate::common::FilePosition;
6use crate::idl;
7
8use super::errors::ValidationError;
9use super::fieldset::Fieldset;
10use super::fqtn::FQTN;
11use super::namespace::Namespace;
12use super::options::Range;
13use super::r#enum::Enum;
14use super::r#struct::Struct;
15use super::typemap::TypeMap;
16
17#[derive(Clone)]
18pub enum Type {
19    // builtin types
20    None,
21    Boolean,
22    Integer,
23    Float,
24    String,
25    UUID,
26    Date,
27    Time,
28    DateTime,
29    // complex types
30    Option(Box<Type>),
31    Result(Box<Type>, Box<Type>),
32    Array(Box<Array>),
33    Map(Box<Map>),
34    // named
35    Ref(TypeRef),
36    // builtin (user provided)
37    Builtin(String),
38}
39
40#[derive(Clone)]
41pub enum TypeRef {
42    Enum(EnumRef),
43    Struct(StructRef),
44    Fieldset(FieldsetRef),
45    Unresolved { fqtn: FQTN, generics: Vec<Type> },
46}
47
48#[derive(Clone)]
49pub struct EnumRef {
50    pub enum_: Weak<RefCell<Enum>>,
51    pub generics: Vec<Type>,
52}
53#[derive(Clone)]
54
55pub struct StructRef {
56    pub struct_: Weak<RefCell<Struct>>,
57    pub generics: Vec<Type>,
58}
59
60#[derive(Clone)]
61pub struct FieldsetRef {
62    pub fieldset: Weak<RefCell<Fieldset>>,
63    pub generics: Vec<Type>,
64}
65
66#[derive(Clone)]
67pub struct Array {
68    pub length: Range,
69    pub item_type: Type,
70}
71
72#[derive(Clone)]
73pub struct Map {
74    pub length: Range,
75    pub key_type: Type,
76    pub value_type: Type,
77}
78
79#[derive(Clone)]
80pub enum UserDefinedType {
81    Enum(Rc<RefCell<Enum>>),
82    Struct(Rc<RefCell<Struct>>),
83    Fieldset(Rc<RefCell<Fieldset>>),
84}
85
86impl Type {
87    pub(crate) fn from_idl_ref(
88        ityperef: &idl::TypeRef,
89        ns: &Namespace,
90        builtin_types: &HashMap<String, String>,
91    ) -> Self {
92        // FIXME this should fail with an error when fqtn.ns is not empty
93        match ityperef.name.as_str() {
94            "None" => Self::None,
95            "Boolean" => Self::Boolean,
96            "Integer" => Self::Integer,
97            "Float" => Self::Float,
98            "String" => Self::String,
99            "UUID" => Self::UUID,
100            "Date" => Self::Date,
101            "Time" => Self::Time,
102            "DateTime" => Self::DateTime,
103            "Option" => Self::Option(Box::new(Type::from_idl(
104                &ityperef.generics[0],
105                ns,
106                &builtin_types,
107            ))),
108            "Result" => Self::Result(
109                Box::new(Type::from_idl(&ityperef.generics[0], ns, &builtin_types)),
110                Box::new(Type::from_idl(&ityperef.generics[1], ns, &builtin_types)),
111            ),
112            name => match builtin_types.get(name) {
113                Some(value) => Self::Builtin(value.to_owned()),
114                None => Self::Ref(TypeRef::from_idl(ityperef, ns, &builtin_types)),
115            },
116        }
117    }
118    pub(crate) fn from_idl(
119        itype: &idl::Type,
120        ns: &Namespace,
121        builtin_types: &HashMap<String, String>,
122    ) -> Self {
123        match itype {
124            idl::Type::Ref(ityperef) => Self::from_idl_ref(&ityperef, &ns, &builtin_types),
125            idl::Type::Array(item_type) => Self::Array(Box::new(Array {
126                item_type: Self::from_idl(item_type, ns, &builtin_types),
127                length: Range {
128                    start: None,
129                    end: None,
130                }, // FIXME
131            })),
132            idl::Type::Map(key_type, value_type) => Self::Map(Box::new(Map {
133                key_type: Self::from_idl(key_type, ns, &builtin_types),
134                value_type: Self::from_idl(value_type, ns, &builtin_types),
135                length: Range {
136                    start: None,
137                    end: None,
138                }, // FIXME
139            })),
140        }
141    }
142    pub(crate) fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
143        match self {
144            Self::None
145            | Self::Boolean
146            | Self::Integer
147            | Self::Float
148            | Self::String
149            | Self::UUID
150            | Self::Date
151            | Self::Time
152            | Self::DateTime => Ok(()),
153            // complex types
154            Self::Option(some) => some.resolve(type_map),
155            Self::Result(ok, err) => {
156                ok.resolve(type_map)?;
157                err.resolve(type_map)?;
158                Ok(())
159            }
160            Self::Array(array) => array.resolve(type_map),
161            Self::Map(map) => map.resolve(type_map),
162            // named
163            Self::Ref(typeref) => typeref.resolve(type_map),
164            // builtin (user defined)
165            Self::Builtin(_) => Ok(()),
166        }
167    }
168    /// Returns wether this type is scalar type or not.
169    pub(crate) fn is_scalar(&self) -> bool {
170        match self {
171            Self::None
172            | Self::Boolean
173            | Self::Integer
174            | Self::Float
175            | Self::String
176            | Self::UUID
177            | Self::Date
178            | Self::Time
179            | Self::DateTime => true,
180            Self::Option(type_) => type_.is_scalar(),
181            Self::Result(_, _) => false,
182            Self::Array(_) => false,
183            Self::Map(_) => false,
184            Self::Ref(_) => false,
185            Self::Builtin(_) => true,
186        }
187    }
188}
189
190impl TypeRef {
191    pub(crate) fn from_idl(
192        ityperef: &idl::TypeRef,
193        ns: &Namespace,
194        builtin_types: &HashMap<String, String>,
195    ) -> Self {
196        Self::Unresolved {
197            fqtn: FQTN::from_idl(ityperef, ns),
198            generics: ityperef
199                .generics
200                .iter()
201                .map(|itype| Type::from_idl(itype, ns, &builtin_types))
202                .collect(),
203        }
204    }
205    pub(crate) fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
206        if let Self::Unresolved { fqtn, generics } = self {
207            let ud_type = type_map.get(fqtn);
208            let position = FilePosition { line: 0, column: 0 }; // FIXME
209            *self = match ud_type {
210                Some(ud_type) => {
211                    if generics.len() != ud_type.generics().len() {
212                        return Err(ValidationError::GenericsMissmatch {
213                            fqtn: fqtn.clone(),
214                            position,
215                        });
216                    }
217                    match ud_type {
218                        UserDefinedType::Enum(enum_) => TypeRef::Enum(EnumRef {
219                            enum_: Rc::downgrade(&enum_),
220                            generics: generics.clone(),
221                        }),
222                        UserDefinedType::Struct(struct_) => TypeRef::Struct(StructRef {
223                            struct_: Rc::downgrade(&struct_),
224                            generics: generics.clone(),
225                        }),
226                        UserDefinedType::Fieldset(fieldset) => TypeRef::Fieldset(FieldsetRef {
227                            fieldset: Rc::downgrade(&fieldset),
228                            generics: generics.clone(),
229                        }),
230                    }
231                }
232                None => {
233                    return Err(ValidationError::NoSuchType {
234                        fqtn: fqtn.clone(),
235                        position,
236                    })
237                }
238            }
239        }
240        Ok(())
241    }
242    pub fn fqtn(&self) -> FQTN {
243        match self {
244            TypeRef::Enum(enum_) => enum_.enum_.upgrade().unwrap().borrow().fqtn.clone(),
245            TypeRef::Struct(struct_) => struct_.struct_.upgrade().unwrap().borrow().fqtn.clone(),
246            TypeRef::Fieldset(fieldset) => {
247                fieldset.fieldset.upgrade().unwrap().borrow().fqtn.clone()
248            }
249            TypeRef::Unresolved { fqtn, generics: _ } => fqtn.clone(),
250        }
251    }
252    pub fn generics(&self) -> &Vec<Type> {
253        match self {
254            TypeRef::Enum(enum_) => &enum_.generics,
255            TypeRef::Struct(struct_) => &struct_.generics,
256            TypeRef::Fieldset(fieldset) => &fieldset.generics,
257            TypeRef::Unresolved { fqtn: _, generics } => generics,
258        }
259    }
260}
261
262impl Array {
263    pub(crate) fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
264        self.item_type.resolve(type_map)
265    }
266}
267
268impl Map {
269    pub(crate) fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
270        self.key_type.resolve(type_map)?;
271        self.value_type.resolve(type_map)?;
272        Ok(())
273    }
274}
275
276impl UserDefinedType {
277    pub fn fqtn(&self) -> FQTN {
278        match self {
279            Self::Enum(t) => t.borrow().fqtn.clone(),
280            Self::Fieldset(t) => t.borrow().fqtn.clone(),
281            Self::Struct(t) => t.borrow().fqtn.clone(),
282        }
283    }
284    pub(crate) fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
285        match self {
286            Self::Enum(t) => t.borrow_mut().resolve(type_map),
287            Self::Fieldset(t) => t.borrow_mut().resolve(type_map),
288            Self::Struct(t) => t.borrow_mut().resolve(type_map),
289        }
290    }
291    pub(crate) fn generics(&self) -> Vec<String> {
292        match self {
293            Self::Enum(t) => t.borrow().generics.clone(),
294            Self::Fieldset(t) => t.borrow().generics.clone(),
295            Self::Struct(t) => t.borrow().generics.clone(),
296        }
297    }
298}