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