@@ -104,8 +104,8 @@ pub enum Encoding {
104
104
/// are possible for the type.
105
105
///
106
106
/// A `BitField(_, Some(_))` and a `BitField(_, None)` do _not_ compare
107
- /// equal; instead, you should set the bitfield depending on the target
108
- /// platform.
107
+ /// equal; instead, you should set the bitfield correctly depending on the
108
+ /// target platform.
109
109
BitField ( u8 , Option < & ' static ( u64 , Encoding ) > ) ,
110
110
/// A pointer to the given type.
111
111
///
@@ -129,12 +129,18 @@ pub enum Encoding {
129
129
/// It is not uncommon for the name to be `"?"`.
130
130
///
131
131
/// Corresponds to the `"{" name "=" fields... "}"` code.
132
+ ///
133
+ /// Note that the `=` may be omitted in some situations; this is
134
+ /// considered equal to the case where there are no fields.
132
135
Struct ( & ' static str , & ' static [ Encoding ] ) ,
133
- /// A union with the given name and fields .
136
+ /// A union with the given name and members .
134
137
///
135
- /// The order of the fields must match the order of the order in this.
138
+ /// The order of the members must match the order of the order in this.
139
+ ///
140
+ /// Corresponds to the `"(" name "=" members... ")"` code.
136
141
///
137
- /// Corresponds to the `"(" name "=" fields... ")"` code.
142
+ /// Note that the `=` may be omitted in some situations; this is
143
+ /// considered equal to the case where there are no members.
138
144
Union ( & ' static str , & ' static [ Encoding ] ) ,
139
145
// TODO: "Vector" types have the '!' encoding, but are not implemented in
140
146
// clang
@@ -189,6 +195,9 @@ impl Encoding {
189
195
/// - Structs or unions behind multiple pointers are considered
190
196
/// equivalent, since Objective-C compilers strip this information to
191
197
/// avoid unnecessary nesting.
198
+ /// - Structs or unions with no fields/members are considered to represent
199
+ /// "opqaue" types, and will therefore be equivalent to all other
200
+ /// structs / unions.
192
201
///
193
202
/// The comparison may be changed in the future to e.g. ignore struct
194
203
/// names or similar changes that may be required because of limitations
@@ -197,7 +206,7 @@ impl Encoding {
197
206
/// For example, you should not rely on two equivalent encodings to have
198
207
/// the same size or ABI - that is provided on a best-effort basis.
199
208
pub fn equivalent_to ( & self , other : & Self ) -> bool {
200
- compare_encodings ( self , NestingLevel :: new ( ) , other, NestingLevel :: new ( ) , false )
209
+ compare_encodings ( self , other, NestingLevel :: new ( ) , false )
201
210
}
202
211
203
212
/// Check if an encoding is equivalent to the given string representation.
@@ -223,7 +232,7 @@ impl Encoding {
223
232
/// See [`Encoding::equivalent_to`] for details about the meaning of
224
233
/// "equivalence".
225
234
pub fn equivalent_to_box ( & self , other : & EncodingBox ) -> bool {
226
- compare_encodings ( self , NestingLevel :: new ( ) , other, NestingLevel :: new ( ) , false )
235
+ compare_encodings ( self , other, NestingLevel :: new ( ) , false )
227
236
}
228
237
}
229
238
@@ -235,7 +244,7 @@ impl Encoding {
235
244
/// Objective-C compilers.
236
245
impl fmt:: Display for Encoding {
237
246
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
238
- write ! ( f , "{}" , Helper :: new( self , NestingLevel :: new( ) ) )
247
+ Helper :: new ( self ) . fmt ( f , NestingLevel :: new ( ) )
239
248
}
240
249
}
241
250
@@ -303,16 +312,16 @@ mod tests {
303
312
304
313
// Check equivalence comparisons
305
314
assert!( E . equivalent_to( & E ) , "equivalent self" ) ;
306
- assert!( E . equivalent_to_str( $string) , "equivalent self string" ) ;
315
+ assert!( E . equivalent_to_str( $string) , "equivalent self string {}" , $string ) ;
307
316
assert!( E . equivalent_to_box( & boxed) , "equivalent self boxed" ) ;
308
317
$(
309
- assert!( E . equivalent_to( & $equivalent_encoding) , "equivalent encoding" ) ;
318
+ assert!( E . equivalent_to( & $equivalent_encoding) , "equivalent encoding {}" , $equivalent_encoding ) ;
310
319
assert!( E . equivalent_to_str( & $equivalent_encoding. to_string( ) ) , "equivalent encoding string" ) ;
311
320
let boxed = EncodingBox :: from_str( & $equivalent_encoding. to_string( ) ) . expect( "parse equivalent encoding" ) ;
312
321
assert!( E . equivalent_to_box( & boxed) , "equivalent encoding boxed" ) ;
313
322
) *
314
323
$(
315
- assert!( E . equivalent_to_str( $equivalent_string) , "equivalent string" ) ;
324
+ assert!( E . equivalent_to_str( $equivalent_string) , "equivalent string {}" , $equivalent_string ) ;
316
325
let boxed = EncodingBox :: from_str( $equivalent_string) . expect( "parse equivalent string" ) ;
317
326
assert!( E . equivalent_to_box( & boxed) , "equivalent string boxed" ) ;
318
327
) *
@@ -447,52 +456,61 @@ mod tests {
447
456
448
457
fn struct_() {
449
458
Encoding::Struct(" SomeStruct ", &[Encoding::Char, Encoding::Int]);
459
+ ~Encoding::Struct(" SomeStruct ", &[]);
450
460
!Encoding::Union(" SomeStruct ", &[Encoding::Char, Encoding::Int]);
451
461
!Encoding::Int;
452
462
!Encoding::Struct(" SomeStruct ", &[Encoding::Int]);
453
463
!Encoding::Struct(" SomeStruct ", &[Encoding::Char, Encoding::Int, Encoding::Int]);
454
464
!Encoding::Struct(" SomeStruct ", &[Encoding::Int, Encoding::Char]);
455
465
!Encoding::Struct(" AnotherName ", &[Encoding::Char, Encoding::Int]);
456
466
" { SomeStruct =ci} ";
457
- ! " { SomeStruct =ci ";
467
+ ~ " { SomeStruct =} ";
458
468
!" { SomeStruct } ";
459
- !" { SomeStruct =} ";
469
+ !" { SomeStruct =ic} ";
470
+ !" { SomeStruct =malformed";
460
471
}
461
472
462
473
fn pointer_struct() {
463
474
Encoding::Pointer(&Encoding::Struct(" SomeStruct ", &[Encoding::Char, Encoding::Int]));
475
+ ~Encoding::Pointer(&Encoding::Struct(" SomeStruct ", &[]));
464
476
!Encoding::Pointer(&Encoding::Struct(" SomeStruct ", &[Encoding::Int, Encoding::Char]));
465
477
!Encoding::Pointer(&Encoding::Struct(" AnotherName ", &[Encoding::Char, Encoding::Int]));
466
478
" ^{ SomeStruct =ci} ";
467
- ! " ^{ SomeStruct =ci ";
479
+ ~ " ^{ SomeStruct =} ";
468
480
!" ^{ SomeStruct } ";
469
- !" ^{ SomeStruct =} ";
481
+ !" ^{ SomeStruct =ic} ";
482
+ !" ^{ SomeStruct =malformed";
470
483
}
471
484
472
485
fn pointer_pointer_struct() {
473
486
Encoding::Pointer(&Encoding::Pointer(&Encoding::Struct(" SomeStruct ", &[Encoding::Char, Encoding::Int])));
487
+ ~Encoding::Pointer(&Encoding::Pointer(&Encoding::Struct(" SomeStruct ", &[])));
474
488
~Encoding::Pointer(&Encoding::Pointer(&Encoding::Struct(" SomeStruct ", &[Encoding::Int, Encoding::Char])));
475
489
!Encoding::Pointer(&Encoding::Pointer(&Encoding::Struct(" AnotherName ", &[Encoding::Char, Encoding::Int])));
476
490
" ^^{ SomeStruct } ";
477
- !" ^^{ SomeStruct =ci} ";
478
- !" ^^{ SomeStruct =ii} ";
479
- !" ^^{ SomeStruct =ci";
480
491
!" ^^{ SomeStruct =} ";
492
+ !" ^^{ SomeStruct =ci} ";
493
+ !" ^^{ SomeStruct =ic} ";
494
+ !" ^^{ AnotherName =ic} ";
495
+ !" ^^{ SomeStruct =malformed";
481
496
}
482
497
483
498
fn atomic_struct() {
484
499
Encoding::Atomic(&Encoding::Struct(" SomeStruct ", &[Encoding::Char, Encoding::Int]));
500
+ ~Encoding::Atomic(&Encoding::Struct(" SomeStruct ", &[]));
485
501
~Encoding::Atomic(&Encoding::Struct(" SomeStruct ", &[Encoding::Int, Encoding::Char]));
486
502
!Encoding::Atomic(&Encoding::Struct(" AnotherName ", &[Encoding::Char, Encoding::Int]));
487
503
" A { SomeStruct } ";
488
- !" A { SomeStruct =ci} ";
489
- !" A { SomeStruct =ci";
490
504
!" A { SomeStruct =} ";
505
+ !" A { SomeStruct =ci} ";
506
+ !" A { SomeStruct =ic} ";
507
+ !" A { SomeStruct =malformed";
491
508
}
492
509
493
510
fn empty_struct() {
494
511
Encoding::Struct(" SomeStruct ", &[]);
495
512
" { SomeStruct =} ";
513
+ ~" { SomeStruct =ci} ";
496
514
!" { SomeStruct } ";
497
515
}
498
516
@@ -554,12 +572,25 @@ mod tests {
554
572
]
555
573
);
556
574
" { abc=^[ 8 B ] ( def=@?) ^^b255c?} ";
575
+ ~" { abc=} ";
576
+ !" { abc} ";
557
577
}
558
578
559
579
fn identifier() {
560
580
Encoding::Struct(" _abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", &[]);
561
581
" { _abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=} ";
562
582
}
583
+
584
+ // Regression test. The encoding of the `CGLContextObj` object changed
585
+ // between versions of macOS. As such, this is something that we must
586
+ // be prepared to handle.
587
+ fn cgl_context_obj() {
588
+ Encoding::Pointer(&Encoding::Struct(" _CGLContextObject", &[]));
589
+ " ^{ _CGLContextObject=} ";
590
+ ~" ^{ _CGLContextObject=^{ __GLIContextRec} { __GLIFunctionDispatchRec=^?^?^?^?^?} ^{ _CGLPrivateObject} ^v} ";
591
+ !" ^{ _CGLContextObject} ";
592
+ !" ^{ SomeOtherStruct =} ";
593
+ }
563
594
}
564
595
565
596
#[test]
@@ -592,7 +623,7 @@ mod tests {
592
623
let parsed = EncodingBox :: from_str( s) . unwrap( ) ;
593
624
let expected = EncodingBox :: Struct (
594
625
"S" . to_string( ) ,
595
- Some ( vec![ EncodingBox :: Block , EncodingBox :: Block ] ) ,
626
+ vec![ EncodingBox :: Block , EncodingBox :: Block ] ,
596
627
) ;
597
628
assert_eq!( parsed, expected) ;
598
629
0 commit comments