• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use quickcheck::{Arbitrary, Gen};
2 use std::fmt;
3 
4 /// BaseTypeC is used in generation of C headers to represent the C language's
5 /// primitive types as well as `void*`.
6 #[derive(Debug, Clone)]
7 pub struct BaseTypeC {
8     /// String representation of C type.
9     pub def: String,
10 }
11 
12 /// TypeQualifierC is used in generation of C headers to represent qualifiers
13 /// such as `const`.
14 #[derive(Debug, Clone)]
15 pub struct TypeQualifierC {
16     /// String representation of C type qualifier.
17     pub def: String,
18 }
19 
20 /// PointerLevelC is used in generation of C headers to represent number of
21 /// `*` for pointer types.
22 #[derive(Debug, Clone)]
23 pub struct PointerLevelC {
24     /// String representation of C declaration's pointer level.
25     pub def: String,
26 }
27 
28 /// ArrayDimensionC is used in generation of C headers to represent number of
29 /// `[]` used to define array types.
30 #[derive(Debug, Clone)]
31 pub struct ArrayDimensionC {
32     /// String representation of C declaration's array dimension.
33     pub def: String,
34 }
35 
36 /// BasicTypeDeclarationC is used in generation of C headers to represent
37 /// declarations outside of function pointers that take the form
38 /// `BaseTypeC` + `TypeQualifierC` + `PointerLevelC` + `ident_id`.
39 #[derive(Debug, Clone)]
40 pub struct BasicTypeDeclarationC {
41     /// The declaration's base type, i.e. `int`.
42     pub type_name: BaseTypeC,
43     /// The declaration's type qualifier, i.e. `const`.
44     pub type_qualifier: TypeQualifierC,
45     /// The declaration's pointer level, i.e. `***`.
46     pub pointer_level: PointerLevelC,
47     /// The declaration's array dimension, i.e. [][][].
48     pub array_dimension: ArrayDimensionC,
49     /// The declaration's identifier, i.e. ident_N.
50     pub ident_id: String,
51 }
52 
53 /// StructDeclarationC is used in generation of C headers to represent the
54 /// definition of a struct type.
55 #[derive(Debug, Clone)]
56 pub struct StructDeclarationC {
57     /// The declaration's fields.
58     pub fields: DeclarationListC,
59     /// The declaration's array dimension, i.e. [][][].
60     pub array_dimension: ArrayDimensionC,
61     /// The declaration's identifier, i.e. struct_N.
62     pub ident_id: String,
63 }
64 
65 /// UnionDeclarationC is used in generation of C headers to represent the
66 /// definition of a union type.
67 #[derive(Debug, Clone)]
68 pub struct UnionDeclarationC {
69     /// The declaration's fields.
70     pub fields: DeclarationListC,
71     /// The declaration's array dimension, i.e. [][][].
72     pub array_dimension: ArrayDimensionC,
73     /// The declaration's identifier, i.e. union_N.
74     pub ident_id: String,
75 }
76 
77 /// FunctionPointerDeclarationC is used in generation of C headers to represent
78 /// the definition of a function pointer type.
79 #[derive(Debug, Clone)]
80 pub struct FunctionPointerDeclarationC {
81     /// The function's type qualifier, i.e. `const`.
82     pub type_qualifier: TypeQualifierC,
83     /// The function's return type, i.e. `int`.
84     pub type_name: BaseTypeC,
85     /// The function's pointer level, i.e. `***`.
86     pub pointer_level: PointerLevelC,
87     /// The function's parameters.
88     pub params: ParameterListC,
89     /// The declaration's identifier, i.e. func_ptr_N.
90     pub ident_id: String,
91 }
92 
93 /// FunctionPrototypeC is used in generation of C headers to represent the
94 /// definition of a function prototype.
95 #[derive(Debug, Clone)]
96 pub struct FunctionPrototypeC {
97     /// The function's type qualifier, i.e. `const`.
98     pub type_qualifier: TypeQualifierC,
99     /// The function's return type, i.e. `int`.
100     pub type_name: BaseTypeC,
101     /// The function's pointer level, i.e. `***`.
102     pub pointer_level: PointerLevelC,
103     /// The function's parameters.
104     pub params: ParameterListC,
105     /// The prototype's identifier, i.e. `func_N`.
106     pub ident_id: String,
107 }
108 
109 /// ParameterC is used in generation of C headers to represent the
110 /// definition function parameters.
111 #[derive(Debug, Clone)]
112 pub struct ParameterC {
113     /// The parameter's type qualifier, i.e. `const`.
114     pub type_qualifier: TypeQualifierC,
115     /// The parameter's base type, i.e. `int`.
116     pub type_name: BaseTypeC,
117     /// The parameter's pointer level, i.e. `***`.
118     pub pointer_level: PointerLevelC,
119 }
120 
121 /// ParameterListC is used in generation of C headers to represent a list of
122 /// definitions of function parameters.
123 #[derive(Debug, Clone)]
124 pub struct ParameterListC {
125     /// Parameters that define a C function signature.
126     pub params: Vec<ParameterC>,
127 }
128 
129 /// DeclarationC is used in generation of C headers to represent all supported
130 /// C type declarations allowed in the generated header.
131 #[derive(Debug, Clone)]
132 pub enum DeclarationC {
133     /// Function prototype declaration kind.
134     FunctionDecl(FunctionPrototypeC),
135     /// Function pointer declaration kind.
136     FunctionPtrDecl(FunctionPointerDeclarationC),
137     /// Struct declaration kind.
138     StructDecl(StructDeclarationC),
139     /// Union declaration kind.
140     UnionDecl(UnionDeclarationC),
141     /// Basic type declaration kind.
142     VariableDecl(BasicTypeDeclarationC),
143 }
144 
145 /// DeclarationListC is used in generation of C headers to represent a list of
146 /// declarations.
147 #[derive(Debug, Clone)]
148 pub struct DeclarationListC {
149     /// Grouping of C declarations.
150     pub decls: Vec<DeclarationC>,
151 }
152 
153 /// HeaderC is used in generation of C headers to represent a collection of
154 /// declarations.
155 #[derive(Clone)]
156 pub struct HeaderC {
157     /// The header's declarations.
158     pub def: DeclarationListC,
159 }
160 
161 /// MakeUnique is used in generation of C headers to make declaration
162 /// identifiers unique by incorporating the `stamp` parameter into it's name.
163 trait MakeUnique {
make_unique(&mut self, stamp: usize)164     fn make_unique(&mut self, stamp: usize);
165 }
166 
167 /// MakeUnique is used in generation of C headers to make DeclarationC
168 /// identifiers unique.
169 impl MakeUnique for DeclarationC {
make_unique(&mut self, stamp: usize)170     fn make_unique(&mut self, stamp: usize) {
171         match *self {
172             DeclarationC::FunctionDecl(ref mut d) => d.make_unique(stamp),
173             DeclarationC::FunctionPtrDecl(ref mut d) => d.make_unique(stamp),
174             DeclarationC::StructDecl(ref mut d) => d.make_unique(stamp),
175             DeclarationC::UnionDecl(ref mut d) => d.make_unique(stamp),
176             DeclarationC::VariableDecl(ref mut d) => d.make_unique(stamp),
177         }
178     }
179 }
180 
181 /// A qucickcheck trait for describing how DeclarationC types can be
182 /// randomly generated and shrunk.
183 impl Arbitrary for DeclarationC {
arbitrary(g: &mut Gen) -> DeclarationC184     fn arbitrary(g: &mut Gen) -> DeclarationC {
185         match gen_range(g, 0, 5) {
186             0 => DeclarationC::FunctionDecl(FunctionPrototypeC::arbitrary(g)),
187             1 => DeclarationC::FunctionPtrDecl(
188                 FunctionPointerDeclarationC::arbitrary(g),
189             ),
190             2 => DeclarationC::StructDecl(StructDeclarationC::arbitrary(g)),
191             3 => DeclarationC::UnionDecl(UnionDeclarationC::arbitrary(g)),
192             4 => {
193                 DeclarationC::VariableDecl(BasicTypeDeclarationC::arbitrary(g))
194             }
195             _ => unreachable!(),
196         }
197     }
198 }
199 
200 /// Enables to string and format for DeclarationC types.
201 impl fmt::Display for DeclarationC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result202     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203         match *self {
204             DeclarationC::FunctionPtrDecl(ref d) => write!(f, "{}", d),
205             DeclarationC::StructDecl(ref d) => write!(f, "{}", d),
206             DeclarationC::UnionDecl(ref d) => write!(f, "{}", d),
207             DeclarationC::VariableDecl(ref d) => write!(f, "{}", d),
208             DeclarationC::FunctionDecl(ref d) => write!(f, "{}", d),
209         }
210     }
211 }
212 
213 /// A qucickcheck trait for describing how DeclarationListC types can be
214 /// randomly generated and shrunk.
215 impl Arbitrary for DeclarationListC {
arbitrary(g: &mut Gen) -> DeclarationListC216     fn arbitrary(g: &mut Gen) -> DeclarationListC {
217         DeclarationListC {
218             decls: Arbitrary::arbitrary(g),
219         }
220     }
221 }
222 
223 /// Enables to string and format for DeclarationListC types.
224 impl fmt::Display for DeclarationListC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result225     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226         let mut display = String::new();
227         for decl in &self.decls {
228             display += &format!("{}", decl);
229         }
230         write!(f, "{}", display)
231     }
232 }
233 
234 /// A quickcheck trait for describing how BaseTypeC types can be
235 /// randomly generated and shrunk.
236 impl Arbitrary for BaseTypeC {
arbitrary(g: &mut Gen) -> BaseTypeC237     fn arbitrary(g: &mut Gen) -> BaseTypeC {
238         // Special case `long double` until issue #550 is resolved.
239         let base_type = vec![
240             "char",
241             "signed char",
242             "unsigned char",
243             "short",
244             "short int",
245             "signed short",
246             "signed short int",
247             "unsigned short",
248             "unsigned short int",
249             "int",
250             "signed",
251             "signed int",
252             "unsigned",
253             "unsigned int",
254             "long",
255             "long int",
256             "signed long",
257             "signed long int",
258             "unsigned long",
259             "unsigned long int",
260             "long long",
261             "long long int",
262             "signed long long",
263             "signed long long int",
264             "unsigned long long",
265             "unsigned long long int",
266             "float",
267             "double",
268             #[cfg(feature = "long-doubles")]
269             "long double",
270             "void*",
271         ];
272         BaseTypeC {
273             def: String::from(*g.choose(&base_type).unwrap()),
274         }
275     }
276 }
277 
278 /// Enables to string and format for BaseTypeC types,
279 impl fmt::Display for BaseTypeC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result280     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281         write!(f, "{}", self.def)
282     }
283 }
284 
285 /// A qucickcheck trait for describing how TypeQualifierC types can be
286 /// randomly generated and shrunk.
287 impl Arbitrary for TypeQualifierC {
arbitrary(g: &mut Gen) -> TypeQualifierC288     fn arbitrary(g: &mut Gen) -> TypeQualifierC {
289         let qualifier = vec!["const", ""];
290         TypeQualifierC {
291             def: String::from(*g.choose(&qualifier).unwrap()),
292         }
293     }
294 }
295 
296 /// Enables to string and format for TypeQualifierC types.
297 impl fmt::Display for TypeQualifierC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result298     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299         write!(f, "{}", self.def)
300     }
301 }
302 
303 /// A qucickcheck trait for describing how PointerLevelC types can be
304 /// randomly generated and shrunk.
305 impl Arbitrary for PointerLevelC {
arbitrary(g: &mut Gen) -> PointerLevelC306     fn arbitrary(g: &mut Gen) -> PointerLevelC {
307         PointerLevelC {
308             // 16 is an arbitrary "not too big" number for capping pointer level.
309             def: (0..gen_range(g, 0, 16)).map(|_| "*").collect::<String>(),
310         }
311     }
312 }
313 
314 /// Enables to string and format for PointerLevelC types.
315 impl fmt::Display for PointerLevelC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result316     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317         write!(f, "{}", self.def)
318     }
319 }
320 
321 /// A qucickcheck trait for describing how ArrayDimensionC types can be
322 /// randomly generated and shrunk.
323 impl Arbitrary for ArrayDimensionC {
arbitrary(g: &mut Gen) -> ArrayDimensionC324     fn arbitrary(g: &mut Gen) -> ArrayDimensionC {
325         // Keep these small, clang complains when they get too big.
326         let dimensions = gen_range(g, 0, 5);
327         let mut def = String::new();
328 
329         let lower_bound = u64::from(cfg!(feature = "zero-sized-arrays"));
330 
331         for _ in 1..dimensions {
332             // 16 is an arbitrary "not too big" number for capping array size.
333             def += &format!("[{}]", gen_range(g, lower_bound, 16));
334         }
335         ArrayDimensionC { def }
336     }
337 }
338 
339 /// Enables to string and format for ArrayDimensionC types.
340 impl fmt::Display for ArrayDimensionC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result341     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342         write!(f, "{}", self.def)
343     }
344 }
345 
346 /// MakeUnique is used in generation of C headers to make BasicTypeDeclarationC
347 /// identifiers unique.
348 impl MakeUnique for BasicTypeDeclarationC {
make_unique(&mut self, stamp: usize)349     fn make_unique(&mut self, stamp: usize) {
350         self.ident_id += &format!("_{}", stamp);
351     }
352 }
353 
354 /// A qucickcheck trait for describing how BasicTypeDeclarationC types can be
355 /// randomly generated and shrunk.
356 impl Arbitrary for BasicTypeDeclarationC {
arbitrary(g: &mut Gen) -> BasicTypeDeclarationC357     fn arbitrary(g: &mut Gen) -> BasicTypeDeclarationC {
358         BasicTypeDeclarationC {
359             type_qualifier: Arbitrary::arbitrary(g),
360             type_name: Arbitrary::arbitrary(g),
361             pointer_level: Arbitrary::arbitrary(g),
362             array_dimension: Arbitrary::arbitrary(g),
363             ident_id: format!("{}", usize::arbitrary(g)),
364         }
365     }
366 }
367 
368 /// Enables to string and format for BasicTypeDeclarationC types.
369 impl fmt::Display for BasicTypeDeclarationC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result370     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371         write!(
372             f,
373             "{} {} {} ident_{}{};",
374             self.type_qualifier,
375             self.type_name,
376             self.pointer_level,
377             self.ident_id,
378             self.array_dimension
379         )
380     }
381 }
382 
383 /// MakeUnique is used in generation of C headers to make StructDeclarationC
384 /// identifiers unique.
385 impl MakeUnique for StructDeclarationC {
make_unique(&mut self, stamp: usize)386     fn make_unique(&mut self, stamp: usize) {
387         self.ident_id += &format!("_{}", stamp);
388     }
389 }
390 
391 /// A qucickcheck trait for describing how StructDeclarationC types can be
392 /// randomly generated and shrunk.
393 impl Arbitrary for StructDeclarationC {
arbitrary(g: &mut Gen) -> StructDeclarationC394     fn arbitrary(g: &mut Gen) -> StructDeclarationC {
395         // Reduce generator size as a method of putting a bound on recursion.
396         // When size < 1 the empty list is generated.
397         let reduced_size: usize = (g.size() / 2) + 1;
398         let mut decl_list: DeclarationListC =
399             Arbitrary::arbitrary(&mut Gen::new(reduced_size));
400         let mut fields: DeclarationListC = DeclarationListC { decls: vec![] };
401 
402         for (i, decl) in decl_list.decls.iter_mut().enumerate() {
403             match *decl {
404                 DeclarationC::FunctionDecl(_) => {}
405                 ref mut decl => {
406                     decl.make_unique(i);
407                     fields.decls.push(decl.clone());
408                 }
409             }
410         }
411 
412         StructDeclarationC {
413             fields,
414             ident_id: format!("{}", usize::arbitrary(g)),
415             array_dimension: Arbitrary::arbitrary(g),
416         }
417     }
418 }
419 
420 /// Enables to string and format for StructDeclarationC types.
421 impl fmt::Display for StructDeclarationC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result422     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423         write!(
424             f,
425             "struct {{ {} }} struct_{}{};",
426             self.fields, self.ident_id, self.array_dimension
427         )
428     }
429 }
430 
431 /// MakeUnique is used in generation of C headers to make UnionDeclarationC
432 /// identifiers unique.
433 impl MakeUnique for UnionDeclarationC {
make_unique(&mut self, stamp: usize)434     fn make_unique(&mut self, stamp: usize) {
435         self.ident_id += &format!("_{}", stamp);
436     }
437 }
438 
439 /// A qucickcheck trait for describing how UnionDeclarationC types can be
440 /// randomly generated and shrunk.
441 impl Arbitrary for UnionDeclarationC {
arbitrary(g: &mut Gen) -> UnionDeclarationC442     fn arbitrary(g: &mut Gen) -> UnionDeclarationC {
443         // Reduce generator size as a method of putting a bound on recursion.
444         // When size < 1 the empty list is generated.
445         let reduced_size: usize = (g.size() / 2) + 1;
446         let mut decl_list: DeclarationListC =
447             Arbitrary::arbitrary(&mut Gen::new(reduced_size));
448         let mut fields: DeclarationListC = DeclarationListC { decls: vec![] };
449 
450         for (i, decl) in decl_list.decls.iter_mut().enumerate() {
451             match *decl {
452                 DeclarationC::FunctionDecl(_) => {}
453                 ref mut decl => {
454                     decl.make_unique(i);
455                     fields.decls.push(decl.clone());
456                 }
457             }
458         }
459 
460         UnionDeclarationC {
461             fields,
462             ident_id: format!("{}", usize::arbitrary(g)),
463             array_dimension: Arbitrary::arbitrary(g),
464         }
465     }
466 }
467 
468 /// Enables to string and format for UnionDeclarationC types.
469 impl fmt::Display for UnionDeclarationC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result470     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471         write!(
472             f,
473             "union {{ {} }} union_{}{};",
474             self.fields, self.ident_id, self.array_dimension
475         )
476     }
477 }
478 
479 /// MakeUnique is used in generation of C headers to make
480 /// FunctionPointerDeclarationC identifiers unique.
481 impl MakeUnique for FunctionPointerDeclarationC {
make_unique(&mut self, stamp: usize)482     fn make_unique(&mut self, stamp: usize) {
483         self.ident_id += &format!("_{}", stamp);
484     }
485 }
486 
487 /// A qucickcheck trait for describing how FunctionPointerDeclarationC types can
488 /// be randomly generated and shrunk.
489 impl Arbitrary for FunctionPointerDeclarationC {
arbitrary(g: &mut Gen) -> FunctionPointerDeclarationC490     fn arbitrary(g: &mut Gen) -> FunctionPointerDeclarationC {
491         FunctionPointerDeclarationC {
492             type_qualifier: Arbitrary::arbitrary(g),
493             type_name: Arbitrary::arbitrary(g),
494             pointer_level: Arbitrary::arbitrary(g),
495             params: Arbitrary::arbitrary(g),
496             ident_id: format!("{}", usize::arbitrary(g)),
497         }
498     }
499 }
500 
501 /// Enables to string and format for FunctionPointerDeclarationC types.
502 impl fmt::Display for FunctionPointerDeclarationC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result503     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504         write!(
505             f,
506             "{} {} {} (*func_ptr_{})({});",
507             self.type_qualifier,
508             self.type_name,
509             self.pointer_level,
510             self.ident_id,
511             self.params
512         )
513     }
514 }
515 
516 /// MakeUnique is used in generation of C headers to make FunctionPrototypeC
517 /// identifiers unique.
518 impl MakeUnique for FunctionPrototypeC {
make_unique(&mut self, stamp: usize)519     fn make_unique(&mut self, stamp: usize) {
520         self.ident_id += &format!("_{}", stamp);
521     }
522 }
523 
524 /// A qucickcheck trait for describing how FunctionPrototypeC types can be
525 /// randomly generated and shrunk.
526 impl Arbitrary for FunctionPrototypeC {
arbitrary(g: &mut Gen) -> FunctionPrototypeC527     fn arbitrary(g: &mut Gen) -> FunctionPrototypeC {
528         FunctionPrototypeC {
529             type_qualifier: Arbitrary::arbitrary(g),
530             type_name: Arbitrary::arbitrary(g),
531             pointer_level: Arbitrary::arbitrary(g),
532             params: Arbitrary::arbitrary(g),
533             ident_id: format!("{}", usize::arbitrary(g)),
534         }
535     }
536 }
537 
538 /// Enables to string and format for FunctionPrototypeC types.
539 impl fmt::Display for FunctionPrototypeC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result540     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541         write!(
542             f,
543             "{} {} {} func_{}({});",
544             self.type_qualifier,
545             self.type_name,
546             self.pointer_level,
547             self.ident_id,
548             self.params
549         )
550     }
551 }
552 
553 /// A qucickcheck trait for describing how ParameterC types can be
554 /// randomly generated and shrunk.
555 impl Arbitrary for ParameterC {
arbitrary(g: &mut Gen) -> ParameterC556     fn arbitrary(g: &mut Gen) -> ParameterC {
557         ParameterC {
558             type_qualifier: Arbitrary::arbitrary(g),
559             type_name: Arbitrary::arbitrary(g),
560             pointer_level: Arbitrary::arbitrary(g),
561         }
562     }
563 }
564 
565 /// Enables to string and format for ParameterC types.
566 impl fmt::Display for ParameterC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result567     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568         write!(
569             f,
570             "{} {} {}",
571             self.type_qualifier, self.type_name, self.pointer_level
572         )
573     }
574 }
575 
576 /// A qucickcheck trait for describing how ParameterListC types can be
577 /// randomly generated and shrunk.
578 impl Arbitrary for ParameterListC {
arbitrary(g: &mut Gen) -> ParameterListC579     fn arbitrary(g: &mut Gen) -> ParameterListC {
580         ParameterListC {
581             params: Arbitrary::arbitrary(g),
582         }
583     }
584 }
585 
586 /// Enables to string and format for ParameterListC types.
587 impl fmt::Display for ParameterListC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result588     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
589         let mut display = String::new();
590         for (i, p) in self.params.iter().enumerate() {
591             match i {
592                 0 => display += &format!("{}", p),
593                 _ => display += &format!(",{}", p),
594             }
595         }
596         write!(f, "{}", display)
597     }
598 }
599 
600 /// A qucickcheck trait for describing how HeaderC types can be
601 /// randomly generated and shrunk.
602 impl Arbitrary for HeaderC {
arbitrary(g: &mut Gen) -> HeaderC603     fn arbitrary(g: &mut Gen) -> HeaderC {
604         let mut decl_list: DeclarationListC = Arbitrary::arbitrary(g);
605         for (i, decl) in decl_list.decls.iter_mut().enumerate() {
606             decl.make_unique(i);
607         }
608         HeaderC { def: decl_list }
609     }
610 }
611 
612 /// Enables to string and format for HeaderC types.
613 impl fmt::Display for HeaderC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result614     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
615         let mut display = String::new();
616         for decl in &self.def.decls {
617             display += &format!("{}", decl);
618         }
619         write!(f, "{}", display)
620     }
621 }
622 
623 /// Use Display trait for Debug so that any failing property tests report
624 /// generated C code rather than the data structures that contain it.
625 impl fmt::Debug for HeaderC {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result626     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627         write!(f, "{}", self)
628     }
629 }
630 
631 /// FIXME: is this actually uniform?
gen_range(gen: &mut Gen, lo: u64, hi: u64) -> u64632 fn gen_range(gen: &mut Gen, lo: u64, hi: u64) -> u64 {
633     let len = hi - lo;
634     (u64::arbitrary(gen) % len) + lo
635 }
636