weedle/
types.rs

1use crate::attribute::ExtendedAttributeList;
2use crate::common::{Generics, Identifier, Parenthesized, Punctuated};
3use crate::term;
4use crate::Parse;
5
6/// Parses a union of types
7pub type UnionType<'a> = Parenthesized<Punctuated<UnionMemberType<'a>, term!(or)>>;
8
9ast_types! {
10    /// Parses either single type or a union type
11    enum Type<'a> {
12        /// Parses one of the single types
13        Single(enum SingleType<'a> {
14            Any(term!(any)),
15            NonAny(NonAnyType<'a>),
16        }),
17        Union(MayBeNull<UnionType<'a>>),
18    }
19
20    // Parses any single non-any type
21    enum NonAnyType<'a> {
22        Promise(PromiseType<'a>),
23        Integer(MayBeNull<IntegerType>),
24        FloatingPoint(MayBeNull<FloatingPointType>),
25        Boolean(MayBeNull<term!(boolean)>),
26        Byte(MayBeNull<term!(byte)>),
27        Octet(MayBeNull<term!(octet)>),
28        ByteString(MayBeNull<term!(ByteString)>),
29        DOMString(MayBeNull<term!(DOMString)>),
30        USVString(MayBeNull<term!(USVString)>),
31        Sequence(MayBeNull<SequenceType<'a>>),
32        Object(MayBeNull<term!(object)>),
33        Symbol(MayBeNull<term!(symbol)>),
34        Error(MayBeNull<term!(Error)>),
35        ArrayBuffer(MayBeNull<term!(ArrayBuffer)>),
36        DataView(MayBeNull<term!(DataView)>),
37        Int8Array(MayBeNull<term!(Int8Array)>),
38        Int16Array(MayBeNull<term!(Int16Array)>),
39        Int32Array(MayBeNull<term!(Int32Array)>),
40        Uint8Array(MayBeNull<term!(Uint8Array)>),
41        Uint16Array(MayBeNull<term!(Uint16Array)>),
42        Uint32Array(MayBeNull<term!(Uint32Array)>),
43        Uint8ClampedArray(MayBeNull<term!(Uint8ClampedArray)>),
44        Float32Array(MayBeNull<term!(Float32Array)>),
45        Float64Array(MayBeNull<term!(Float64Array)>),
46        ArrayBufferView(MayBeNull<term!(ArrayBufferView)>),
47        BufferSource(MayBeNull<term!(BufferSource)>),
48        FrozenArrayType(MayBeNull<FrozenArrayType<'a>>),
49        ObservableArrayType(MayBeNull<ObservableArrayType<'a>>),
50        RecordType(MayBeNull<RecordType<'a>>),
51        Identifier(MayBeNull<Identifier<'a>>),
52    }
53
54    /// Parses `sequence<Type>`
55    struct SequenceType<'a> {
56        sequence: term!(sequence),
57        generics: Generics<Box<Type<'a>>>,
58    }
59
60    /// Parses `FrozenArray<Type>`
61    struct FrozenArrayType<'a> {
62        frozen_array: term!(FrozenArray),
63        generics: Generics<Box<Type<'a>>>,
64    }
65
66    /// Parses `ObservableArray<Type>`
67    struct ObservableArrayType<'a> {
68        observable_array: term!(ObservableArray),
69        generics: Generics<Box<Type<'a>>>,
70    }
71
72    /// Parses a nullable type. Ex: `object | object??`
73    ///
74    /// `??` means an actual ? not an optional requirement
75    #[derive(Copy)]
76    struct MayBeNull<T> where [T: Parse<'a>] {
77        type_: T,
78        q_mark: Option<term::QMark>,
79    }
80
81    /// Parses a `Promise<Type|undefined>` type
82    struct PromiseType<'a> {
83        promise: term!(Promise),
84        generics: Generics<Box<ReturnType<'a>>>,
85    }
86
87    /// Parses `unsigned? short|long|(long long)`
88    #[derive(Copy)]
89    enum IntegerType {
90        /// Parses `unsigned? long long`
91        #[derive(Copy)]
92        LongLong(struct LongLongType {
93            unsigned: Option<term!(unsigned)>,
94            long_long: (term!(long), term!(long)),
95        }),
96        /// Parses `unsigned? long`
97        #[derive(Copy)]
98        Long(struct LongType {
99            unsigned: Option<term!(unsigned)>,
100            long: term!(long),
101        }),
102        /// Parses `unsigned? short`
103        #[derive(Copy)]
104        Short(struct ShortType {
105            unsigned: Option<term!(unsigned)>,
106            short: term!(short),
107        }),
108    }
109
110    /// Parses `unrestricted? float|double`
111    #[derive(Copy)]
112    enum FloatingPointType {
113        /// Parses `unrestricted? float`
114        #[derive(Copy)]
115        Float(struct FloatType {
116            unrestricted: Option<term!(unrestricted)>,
117            float: term!(float),
118        }),
119        /// Parses `unrestricted? double`
120        #[derive(Copy)]
121        Double(struct DoubleType {
122            unrestricted: Option<term!(unrestricted)>,
123            double: term!(double),
124        }),
125    }
126
127    /// Parses `record<StringType, Type>`
128    struct RecordType<'a> {
129        record: term!(record),
130        generics: Generics<(Box<RecordKeyType<'a>>, term!(,), Box<Type<'a>>)>,
131    }
132
133    /// Parses one of the string types `ByteString|DOMString|USVString` or any other type.
134    enum RecordKeyType<'a> {
135        Byte(term!(ByteString)),
136        DOM(term!(DOMString)),
137        USV(term!(USVString)),
138        NonAny(NonAnyType<'a>),
139    }
140
141    /// Parses one of the member of a union type
142    enum UnionMemberType<'a> {
143        Single(AttributedNonAnyType<'a>),
144        Union(MayBeNull<UnionType<'a>>),
145    }
146
147    /// Parses a const type
148    enum ConstType<'a> {
149        Integer(MayBeNull<IntegerType>),
150        FloatingPoint(MayBeNull<FloatingPointType>),
151        Boolean(MayBeNull<term!(boolean)>),
152        Byte(MayBeNull<term!(byte)>),
153        Octet(MayBeNull<term!(octet)>),
154        Identifier(MayBeNull<Identifier<'a>>),
155    }
156
157    /// Parses the return type which may be `undefined` or any given Type
158    enum ReturnType<'a> {
159        Undefined(term!(undefined)),
160        Type(Type<'a>),
161    }
162
163    /// Parses `[attributes]? type`
164    struct AttributedType<'a> {
165        attributes: Option<ExtendedAttributeList<'a>>,
166        type_: Type<'a>,
167    }
168
169    /// Parses `[attributes]? type` where the type is a single non-any type
170    struct AttributedNonAnyType<'a> {
171        attributes: Option<ExtendedAttributeList<'a>>,
172        type_: NonAnyType<'a>,
173    }
174}
175
176#[cfg(test)]
177mod test {
178    use super::*;
179
180    test!(should_parse_may_be_null { "short" =>
181        "";
182        MayBeNull<crate::types::IntegerType>;
183        q_mark.is_none();
184    });
185
186    test!(should_parse_nullable { "short?" =>
187        "";
188        MayBeNull<crate::types::IntegerType>;
189        q_mark.is_some();
190    });
191
192    test_variants!(
193        ReturnType {
194            Undefined == "undefined",
195            Type == "any",
196        }
197    );
198
199    test_variants!(
200        ConstType {
201            Integer == "short",
202            FloatingPoint == "float",
203            Boolean == "boolean",
204            Byte == "byte",
205            Octet == "octet",
206            Identifier == "name",
207        }
208    );
209
210    test_variants!(
211        NonAnyType {
212            Promise == "Promise<long>",
213            Integer == "long",
214            FloatingPoint == "float",
215            Boolean == "boolean",
216            Byte == "byte",
217            Octet == "octet",
218            ByteString == "ByteString",
219            DOMString == "DOMString",
220            USVString == "USVString",
221            Sequence == "sequence<short>",
222            Object == "object",
223            Symbol == "symbol",
224            Error == "Error",
225            ArrayBuffer == "ArrayBuffer",
226            DataView == "DataView",
227            Int8Array == "Int8Array",
228            Int16Array == "Int16Array",
229            Int32Array == "Int32Array",
230            Uint8Array == "Uint8Array",
231            Uint16Array == "Uint16Array",
232            Uint32Array == "Uint32Array",
233            Uint8ClampedArray == "Uint8ClampedArray",
234            Float32Array == "Float32Array",
235            Float64Array == "Float64Array",
236            ArrayBufferView == "ArrayBufferView",
237            BufferSource == "BufferSource",
238            FrozenArrayType == "FrozenArray<short>",
239            ObservableArrayType == "ObservableArray<short>",
240            RecordType == "record<DOMString, short>",
241            Identifier == "mango"
242        }
243    );
244
245    test_variants!(
246        UnionMemberType {
247            Single == "byte",
248            Union == "([Clamp] unsigned long or byte)"
249        }
250    );
251
252    test_variants!(
253        RecordKeyType {
254            DOM == "DOMString",
255            USV == "USVString",
256            Byte == "ByteString"
257        }
258    );
259
260    test!(should_parse_record_type { "record<DOMString, short>" =>
261        "";
262        RecordType;
263    });
264
265    test!(should_parse_record_type_alt_types { "record<u64, short>" =>
266        "";
267        RecordType;
268    });
269
270    test!(should_parse_double_type { "double" =>
271        "";
272        DoubleType;
273    });
274
275    test!(should_parse_float_type { "float" =>
276        "";
277        FloatType;
278    });
279
280    test_variants!(
281        FloatingPointType {
282            Float == "float",
283            Double == "double"
284        }
285    );
286
287    test!(should_parse_long_long_type { "long long" =>
288        "";
289        LongLongType;
290    });
291
292    test!(should_parse_long_type { "long" =>
293        "";
294        LongType;
295    });
296
297    test!(should_parse_short_type { "short" =>
298        "";
299        ShortType;
300    });
301
302    test_variants!(
303        IntegerType {
304            Short == "short",
305            Long == "long",
306            LongLong == "long long"
307        }
308    );
309
310    test!(should_parse_promise_type { "Promise<short>" =>
311        "";
312        PromiseType;
313    });
314
315    test!(should_parse_frozen_array_type { "FrozenArray<short>" =>
316        "";
317        FrozenArrayType;
318    });
319
320    test!(should_parse_observable_array_type { "ObservableArray<short>" =>
321        "";
322        ObservableArrayType;
323    });
324
325    test!(should_parse_sequence_type { "sequence<short>" =>
326        "";
327        SequenceType;
328    });
329
330    test_variants!(
331        SingleType {
332            Any == "any",
333            NonAny == "Promise<short>",
334        }
335    );
336
337    test_variants!(
338        Type {
339            Single == "short",
340            Union == "(short or float)"
341        }
342    );
343
344    test!(should_parse_attributed_type { "[Named] short" =>
345        "";
346        AttributedType;
347        attributes.is_some();
348    });
349
350    test!(should_parse_type_as_identifier { "DOMStringMap" =>
351        // if type is not parsed as identifier, it is parsed as `DOMString` and 'Map' is left
352        "";
353        crate::types::Type;
354    });
355
356    #[test]
357    fn should_parse_union_member_type_attributed_union() {
358        use crate::types::UnionMemberType;
359        let (rem, parsed) = UnionMemberType::parse("([Clamp] byte or [Named] byte)").unwrap();
360        assert_eq!(rem, "");
361        match parsed {
362            UnionMemberType::Union(MayBeNull {
363                type_:
364                    Parenthesized {
365                        body: Punctuated { list, .. },
366                        ..
367                    },
368                ..
369            }) => {
370                assert_eq!(list.len(), 2);
371
372                match list[0] {
373                    UnionMemberType::Single(AttributedNonAnyType { ref attributes, .. }) => {
374                        assert!(attributes.is_some());
375                    }
376
377                    _ => {
378                        panic!("Failed to parse list[0] attributes");
379                    }
380                };
381
382                match list[1] {
383                    UnionMemberType::Single(AttributedNonAnyType { ref attributes, .. }) => {
384                        assert!(attributes.is_some());
385                    }
386
387                    _ => {
388                        panic!("Failed to parse list[1] attributes");
389                    }
390                };
391            }
392
393            _ => {
394                panic!("Failed to parse");
395            }
396        }
397    }
398}