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