Skip to content

Commit 7e27dae

Browse files
committed
feat(types/objc): Support wider bitfield types in encoding decoder #51
Bitfields now use unsigned long long for spans >32 bits and unsigned __int128 for spans >64 bits. Spans exceeding 128 bits are capped with a warning comment.
1 parent fb8fd7e commit 7e27dae

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

types/objc/type_encoding.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,35 @@ func decodeVector(vectorType string) string {
460460

461461
func decodeBitfield(bitfield string) string {
462462
span := encodingGetSizeOfArguments(bitfield)
463-
return fmt.Sprintf("unsigned int x:%d", span)
463+
return formatBitfieldDecl("x", span)
464+
}
465+
466+
const (
467+
bitfieldWidthUnsignedInt uint = 32
468+
bitfieldWidthUnsignedLongLong uint = 64
469+
bitfieldWidthUnsignedInt128 uint = 128
470+
)
471+
472+
func bitfieldTypeForSpan(span uint) (string, uint) {
473+
switch {
474+
case span <= bitfieldWidthUnsignedInt:
475+
return "unsigned int", span
476+
case span <= bitfieldWidthUnsignedLongLong:
477+
return "unsigned long long", span
478+
case span <= bitfieldWidthUnsignedInt128:
479+
return "unsigned __int128", span
480+
default:
481+
return "unsigned __int128", bitfieldWidthUnsignedInt128
482+
}
483+
}
484+
485+
func formatBitfieldDecl(name string, span uint) string {
486+
typ, effectiveSpan := bitfieldTypeForSpan(span)
487+
decl := fmt.Sprintf("%s %s:%d", typ, name, effectiveSpan)
488+
if effectiveSpan != span {
489+
decl += fmt.Sprintf(" /* unsupported bitfield width %d */", span)
490+
}
491+
return decl
464492
}
465493

466494
func getFieldName(field string) (string, string) {
@@ -516,7 +544,7 @@ func decodeStructOrUnion(typ, kind string) string {
516544

517545
if strings.HasPrefix(field, "b") {
518546
span := encodingGetSizeOfArguments(field)
519-
fields = append(fields, fmt.Sprintf("unsigned int %s:%d;", fieldName, span))
547+
fields = append(fields, formatBitfieldDecl(fieldName, span)+";")
520548
} else if strings.HasPrefix(field, "[") {
521549
array := decodeType(field)
522550
array = strings.TrimSpace(strings.Replace(array, "x", fieldName, 1)) + ";"

types/objc/type_encoding_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ func Test_decodeType(t *testing.T) {
3939
},
4040
want: "unsigned int x:13",
4141
},
42+
{
43+
name: "Test bitfield 128",
44+
args: args{
45+
encType: "b128",
46+
},
47+
want: "unsigned __int128 x:128",
48+
},
49+
{
50+
name: "Test bitfield 200",
51+
args: args{
52+
encType: "b200",
53+
},
54+
want: "unsigned __int128 x:128 /* unsupported bitfield width 200 */",
55+
},
4256
{
4357
name: "Test struct 0",
4458
args: args{
@@ -53,6 +67,20 @@ func Test_decodeType(t *testing.T) {
5367
},
5468
want: "struct { int x0; float x1[3]; unsigned int x2:3; unsigned int x3:2; signed char x4; }",
5569
},
70+
{
71+
name: "Test struct bitfield widths",
72+
args: args{
73+
encType: "{?=ib33b64b128}",
74+
},
75+
want: "struct { int x0; unsigned long long x1:33; unsigned long long x2:64; unsigned __int128 x3:128; }",
76+
},
77+
{
78+
name: "Test struct bitfield width overflow",
79+
args: args{
80+
encType: "{?=b200}",
81+
},
82+
want: "struct { unsigned __int128 x0:128 /* unsupported bitfield width 200 */; }",
83+
},
5684
{
5785
name: "Test struct 3",
5886
args: args{

0 commit comments

Comments
 (0)