objc: encode 64-bit integers as q and Q (#499)
# What issue is this addressing? Closes #493 ## What _type_ of issue is this addressing? bug ## What this PR does | solves encodeType mapped Go's 64-bit integer kinds to the 32-bit @encode spellings: int to "l", and int64, uint and uint64 all to "L", which additionally gave int64 an unsigned spelling. On darwin, which is LP64 on every architecture Go supports, clang spells 64-bit integers "q" and "Q". Argument passing is unaffected because purego marshals from the Go types, but consumers that read the declared width back from the runtime metadata - NSInvocation, NSMethodSignature and forwardInvocation: based proxies, KVC autoboxing from ivar encodings - silently truncate values above 2^32. Check the encoding of each type against clang @encode itself so that the expected encodings cannot drift from the compiler, and assert how encodeFunc assembles a full method signature.
- commit
- f2f42023699cc525d655935f7f262a57faa3ee33
- author
- TotallyGamerJet · · 2026-08-20 17:14 UTC
- committer
- GitHub · · 2026-08-20 17:14 UTC
- parent
- 7d5f4c2
- signature
- GPG Unverified
B5690EEEBB952194The key is unknown
2 files · +190 -6
A objc/encoding_darwin_test.go +184 -0
| @@ -0,0 +1,184 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | package objc | |
| 5 | + | ||
| 6 | + | import ( | |
| 7 | + | "fmt" | |
| 8 | + | "os" | |
| 9 | + | "os/exec" | |
| 10 | + | "path/filepath" | |
| 11 | + | "reflect" | |
| 12 | + | "strings" | |
| 13 | + | "testing" | |
| 14 | + | "unsafe" | |
| 15 | + | ) | |
| 16 | + | ||
| 17 | + | type encodeTypeTestStruct struct { | |
| 18 | + | A int32 | |
| 19 | + | B float64 | |
| 20 | + | } | |
| 21 | + | ||
| 22 | + | var encodeTypeTests = []struct { | |
| 23 | + | typ reflect.Type | |
| 24 | + | cType string | |
| 25 | + | want string | |
| 26 | + | }{ | |
| 27 | + | {reflect.TypeFor[bool](), "_Bool", "B"}, | |
| 28 | + | {reflect.TypeFor[int8](), "signed char", "c"}, | |
| 29 | + | {reflect.TypeFor[uint8](), "unsigned char", "C"}, | |
| 30 | + | {reflect.TypeFor[int16](), "short", "s"}, | |
| 31 | + | {reflect.TypeFor[uint16](), "unsigned short", "S"}, | |
| 32 | + | {reflect.TypeFor[int32](), "int", "i"}, | |
| 33 | + | {reflect.TypeFor[uint32](), "unsigned int", "I"}, | |
| 34 | + | {reflect.TypeFor[int64](), "long long", "q"}, | |
| 35 | + | {reflect.TypeFor[uint64](), "unsigned long long", "Q"}, | |
| 36 | + | {reflect.TypeFor[int](), "long", "q"}, | |
| 37 | + | {reflect.TypeFor[uint](), "unsigned long", "Q"}, | |
| 38 | + | {reflect.TypeFor[float32](), "float", "f"}, | |
| 39 | + | {reflect.TypeFor[float64](), "double", "d"}, | |
| 40 | + | {reflect.TypeFor[string](), "char *", "*"}, | |
| 41 | + | {reflect.TypeFor[unsafe.Pointer](), "void *", "^v"}, | |
| 42 | + | {reflect.TypeFor[*int32](), "int *", "^i"}, | |
| 43 | + | {reflect.TypeFor[**int32](), "int **", "^^i"}, | |
| 44 | + | {reflect.TypeFor[ID](), "id", "@"}, | |
| 45 | + | {reflect.TypeFor[Class](), "Class", "#"}, | |
| 46 | + | {reflect.TypeFor[SEL](), "SEL", ":"}, | |
| 47 | + | {reflect.TypeFor[encodeTypeTestStruct](), "struct encodeTypeTestStruct", "{encodeTypeTestStruct=id}"}, | |
| 48 | + | } | |
| 49 | + | ||
| 50 | + | func TestEncodeType(t *testing.T) { | |
| 51 | + | for _, tt := range encodeTypeTests { | |
| 52 | + | got, err := encodeType(tt.typ, false) | |
| 53 | + | if err != nil { | |
| 54 | + | t.Errorf("encodeType(%v) returned error: %v", tt.typ, err) | |
| 55 | + | continue | |
| 56 | + | } | |
| 57 | + | if got != tt.want { | |
| 58 | + | t.Errorf("encodeType(%v) = %q; want %q (@encode(%s))", tt.typ, got, tt.want, tt.cType) | |
| 59 | + | } | |
| 60 | + | } | |
| 61 | + | } | |
| 62 | + | ||
| 63 | + | // TestEncodeTypeMatchesClang uses the C compiler as an oracle: it compiles a | |
| 64 | + | // program that prints @encode for each C type in encodeTypeTests and checks | |
| 65 | + | // that the expected encodings are the ones the compiler actually produces. | |
| 66 | + | func TestEncodeTypeMatchesClang(t *testing.T) { | |
| 67 | + | out, err := exec.Command("go", "env", "CC").Output() | |
| 68 | + | if err != nil { | |
| 69 | + | t.Fatalf("go env CC: %v", err) | |
| 70 | + | } | |
| 71 | + | compiler := strings.TrimSpace(string(out)) | |
| 72 | + | if compiler == "" { | |
| 73 | + | t.Skip("no C compiler to use as an @encode oracle") | |
| 74 | + | } | |
| 75 | + | if _, err := exec.LookPath(compiler); err != nil { | |
| 76 | + | t.Skipf("no C compiler to use as an @encode oracle: %v", err) | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | var src strings.Builder | |
| 80 | + | src.WriteString("#include <stdio.h>\n#include <objc/objc.h>\n") | |
| 81 | + | src.WriteString("struct encodeTypeTestStruct { int a; double b; };\n") | |
| 82 | + | src.WriteString("int main(void) {\n") | |
| 83 | + | for _, tt := range encodeTypeTests { | |
| 84 | + | fmt.Fprintf(&src, "\tprintf(\"%%s\\n\", @encode(%s));\n", tt.cType) | |
| 85 | + | } | |
| 86 | + | src.WriteString("\treturn 0;\n}\n") | |
| 87 | + | ||
| 88 | + | dir := t.TempDir() | |
| 89 | + | srcFile := filepath.Join(dir, "encode.m") | |
| 90 | + | if err := os.WriteFile(srcFile, []byte(src.String()), 0o644); err != nil { | |
| 91 | + | t.Fatal(err) | |
| 92 | + | } | |
| 93 | + | ||
| 94 | + | // Built for the host architecture rather than GOARCH, unlike the shared | |
| 95 | + | // libraries in the root package's tests: every darwin target Go supports | |
| 96 | + | // is LP64, so these encodings do not vary by architecture, and building | |
| 97 | + | // for the host avoids needing Rosetta to run an amd64 binary on arm64. | |
| 98 | + | exeFile := filepath.Join(dir, "encode") | |
| 99 | + | cmd := exec.Command(compiler, "-Wall", "-Werror", "-o", exeFile, srcFile) | |
| 100 | + | if out, err := cmd.CombinedOutput(); err != nil { | |
| 101 | + | t.Fatalf("compile oracle: %v\n%q\n%s", err, cmd, out) | |
| 102 | + | } | |
| 103 | + | ||
| 104 | + | out, err = exec.Command(exeFile).Output() | |
| 105 | + | if err != nil { | |
| 106 | + | t.Fatalf("run oracle: %v", err) | |
| 107 | + | } | |
| 108 | + | lines := strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") | |
| 109 | + | if len(lines) != len(encodeTypeTests) { | |
| 110 | + | t.Fatalf("oracle printed %d encodings; want %d", len(lines), len(encodeTypeTests)) | |
| 111 | + | } | |
| 112 | + | for i, tt := range encodeTypeTests { | |
| 113 | + | if lines[i] != tt.want { | |
| 114 | + | t.Errorf("@encode(%s) = %q; want %q", tt.cType, lines[i], tt.want) | |
| 115 | + | } | |
| 116 | + | } | |
| 117 | + | } | |
| 118 | + | ||
| 119 | + | // TestEncodeFunc checks how encodeFunc assembles a method signature: the | |
| 120 | + | // return type, the implicit self and _cmd parameters, and the argument order. | |
| 121 | + | // encodeType is checked per type by TestEncodeType, so the cases here vary the | |
| 122 | + | // shape of the signature rather than the types in it. The first case is the | |
| 123 | + | // signature from issue #493, which was recorded as v@:LLLLLLLLS - declaring | |
| 124 | + | // 64-bit arguments as 32-bit made NSInvocation and other consumers of the type | |
| 125 | + | // encoding truncate values above 2^32. | |
| 126 | + | func TestEncodeFunc(t *testing.T) { | |
| 127 | + | tests := []struct { | |
| 128 | + | name string | |
| 129 | + | fn any | |
| 130 | + | want string | |
| 131 | + | }{ | |
| 132 | + | { | |
| 133 | + | name: "void return, 64-bit args", | |
| 134 | + | fn: func(_ ID, _ SEL, a1, a2, a3, a4, a5, a6, a7, a8 uint64, a9 uint16) {}, | |
| 135 | + | want: "v@:QQQQQQQQS", | |
| 136 | + | }, | |
| 137 | + | { | |
| 138 | + | name: "value return, mixed integer kinds", | |
| 139 | + | fn: func(_ ID, _ SEL, a int, b int64, c uint, d uint64) int { return 0 }, | |
| 140 | + | want: "q@:qqQQ", | |
| 141 | + | }, | |
| 142 | + | { | |
| 143 | + | name: "no arguments", | |
| 144 | + | fn: func(_ ID, _ SEL) {}, | |
| 145 | + | want: "v@:", | |
| 146 | + | }, | |
| 147 | + | { | |
| 148 | + | name: "argument order is preserved", | |
| 149 | + | fn: func(_ ID, _ SEL, a int8, b float64, c ID) Class { return 0 }, | |
| 150 | + | want: "#@:cd@", | |
| 151 | + | }, | |
| 152 | + | } | |
| 153 | + | for _, tt := range tests { | |
| 154 | + | t.Run(tt.name, func(t *testing.T) { | |
| 155 | + | got, err := encodeFunc(tt.fn) | |
| 156 | + | if err != nil { | |
| 157 | + | t.Fatal(err) | |
| 158 | + | } | |
| 159 | + | if got != tt.want { | |
| 160 | + | t.Errorf("encodeFunc = %q; want %q", got, tt.want) | |
| 161 | + | } | |
| 162 | + | }) | |
| 163 | + | } | |
| 164 | + | } | |
| 165 | + | ||
| 166 | + | func TestEncodeFuncErrors(t *testing.T) { | |
| 167 | + | tests := []struct { | |
| 168 | + | name string | |
| 169 | + | fn any | |
| 170 | + | }{ | |
| 171 | + | {"not a func", 0}, | |
| 172 | + | {"too many return values", func(_ ID, _ SEL) (int, int) { return 0, 0 }}, | |
| 173 | + | {"missing self and _cmd", func() {}}, | |
| 174 | + | {"missing _cmd", func(_ ID) {}}, | |
| 175 | + | {"unencodable argument", func(_ ID, _ SEL, c chan int) {}}, | |
| 176 | + | } | |
| 177 | + | for _, tt := range tests { | |
| 178 | + | t.Run(tt.name, func(t *testing.T) { | |
| 179 | + | if got, err := encodeFunc(tt.fn); err == nil { | |
| 180 | + | t.Errorf("encodeFunc = %q; want an error", got) | |
| 181 | + | } | |
| 182 | + | }) | |
| 183 | + | } | |
| 184 | + | } | |
| @@ -0,0 +1,184 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | package objc | |||
| 5 | + | ||||
| 6 | + | import ( | |||
| 7 | + | "fmt" | |||
| 8 | + | "os" | |||
| 9 | + | "os/exec" | |||
| 10 | + | "path/filepath" | |||
| 11 | + | "reflect" | |||
| 12 | + | "strings" | |||
| 13 | + | "testing" | |||
| 14 | + | "unsafe" | |||
| 15 | + | ) | |||
| 16 | + | ||||
| 17 | + | type encodeTypeTestStruct struct { | |||
| 18 | + | A int32 | |||
| 19 | + | B float64 | |||
| 20 | + | } | |||
| 21 | + | ||||
| 22 | + | var encodeTypeTests = []struct { | |||
| 23 | + | typ reflect.Type | |||
| 24 | + | cType string | |||
| 25 | + | want string | |||
| 26 | + | }{ | |||
| 27 | + | {reflect.TypeFor[bool](), "_Bool", "B"}, | |||
| 28 | + | {reflect.TypeFor[int8](), "signed char", "c"}, | |||
| 29 | + | {reflect.TypeFor[uint8](), "unsigned char", "C"}, | |||
| 30 | + | {reflect.TypeFor[int16](), "short", "s"}, | |||
| 31 | + | {reflect.TypeFor[uint16](), "unsigned short", "S"}, | |||
| 32 | + | {reflect.TypeFor[int32](), "int", "i"}, | |||
| 33 | + | {reflect.TypeFor[uint32](), "unsigned int", "I"}, | |||
| 34 | + | {reflect.TypeFor[int64](), "long long", "q"}, | |||
| 35 | + | {reflect.TypeFor[uint64](), "unsigned long long", "Q"}, | |||
| 36 | + | {reflect.TypeFor[int](), "long", "q"}, | |||
| 37 | + | {reflect.TypeFor[uint](), "unsigned long", "Q"}, | |||
| 38 | + | {reflect.TypeFor[float32](), "float", "f"}, | |||
| 39 | + | {reflect.TypeFor[float64](), "double", "d"}, | |||
| 40 | + | {reflect.TypeFor[string](), "char *", "*"}, | |||
| 41 | + | {reflect.TypeFor[unsafe.Pointer](), "void *", "^v"}, | |||
| 42 | + | {reflect.TypeFor[*int32](), "int *", "^i"}, | |||
| 43 | + | {reflect.TypeFor[**int32](), "int **", "^^i"}, | |||
| 44 | + | {reflect.TypeFor[ID](), "id", "@"}, | |||
| 45 | + | {reflect.TypeFor[Class](), "Class", "#"}, | |||
| 46 | + | {reflect.TypeFor[SEL](), "SEL", ":"}, | |||
| 47 | + | {reflect.TypeFor[encodeTypeTestStruct](), "struct encodeTypeTestStruct", "{encodeTypeTestStruct=id}"}, | |||
| 48 | + | } | |||
| 49 | + | ||||
| 50 | + | func TestEncodeType(t *testing.T) { | |||
| 51 | + | for _, tt := range encodeTypeTests { | |||
| 52 | + | got, err := encodeType(tt.typ, false) | |||
| 53 | + | if err != nil { | |||
| 54 | + | t.Errorf("encodeType(%v) returned error: %v", tt.typ, err) | |||
| 55 | + | continue | |||
| 56 | + | } | |||
| 57 | + | if got != tt.want { | |||
| 58 | + | t.Errorf("encodeType(%v) = %q; want %q (@encode(%s))", tt.typ, got, tt.want, tt.cType) | |||
| 59 | + | } | |||
| 60 | + | } | |||
| 61 | + | } | |||
| 62 | + | ||||
| 63 | + | // TestEncodeTypeMatchesClang uses the C compiler as an oracle: it compiles a | |||
| 64 | + | // program that prints @encode for each C type in encodeTypeTests and checks | |||
| 65 | + | // that the expected encodings are the ones the compiler actually produces. | |||
| 66 | + | func TestEncodeTypeMatchesClang(t *testing.T) { | |||
| 67 | + | out, err := exec.Command("go", "env", "CC").Output() | |||
| 68 | + | if err != nil { | |||
| 69 | + | t.Fatalf("go env CC: %v", err) | |||
| 70 | + | } | |||
| 71 | + | compiler := strings.TrimSpace(string(out)) | |||
| 72 | + | if compiler == "" { | |||
| 73 | + | t.Skip("no C compiler to use as an @encode oracle") | |||
| 74 | + | } | |||
| 75 | + | if _, err := exec.LookPath(compiler); err != nil { | |||
| 76 | + | t.Skipf("no C compiler to use as an @encode oracle: %v", err) | |||
| 77 | + | } | |||
| 78 | + | ||||
| 79 | + | var src strings.Builder | |||
| 80 | + | src.WriteString("#include <stdio.h>\n#include <objc/objc.h>\n") | |||
| 81 | + | src.WriteString("struct encodeTypeTestStruct { int a; double b; };\n") | |||
| 82 | + | src.WriteString("int main(void) {\n") | |||
| 83 | + | for _, tt := range encodeTypeTests { | |||
| 84 | + | fmt.Fprintf(&src, "\tprintf(\"%%s\\n\", @encode(%s));\n", tt.cType) | |||
| 85 | + | } | |||
| 86 | + | src.WriteString("\treturn 0;\n}\n") | |||
| 87 | + | ||||
| 88 | + | dir := t.TempDir() | |||
| 89 | + | srcFile := filepath.Join(dir, "encode.m") | |||
| 90 | + | if err := os.WriteFile(srcFile, []byte(src.String()), 0o644); err != nil { | |||
| 91 | + | t.Fatal(err) | |||
| 92 | + | } | |||
| 93 | + | ||||
| 94 | + | // Built for the host architecture rather than GOARCH, unlike the shared | |||
| 95 | + | // libraries in the root package's tests: every darwin target Go supports | |||
| 96 | + | // is LP64, so these encodings do not vary by architecture, and building | |||
| 97 | + | // for the host avoids needing Rosetta to run an amd64 binary on arm64. | |||
| 98 | + | exeFile := filepath.Join(dir, "encode") | |||
| 99 | + | cmd := exec.Command(compiler, "-Wall", "-Werror", "-o", exeFile, srcFile) | |||
| 100 | + | if out, err := cmd.CombinedOutput(); err != nil { | |||
| 101 | + | t.Fatalf("compile oracle: %v\n%q\n%s", err, cmd, out) | |||
| 102 | + | } | |||
| 103 | + | ||||
| 104 | + | out, err = exec.Command(exeFile).Output() | |||
| 105 | + | if err != nil { | |||
| 106 | + | t.Fatalf("run oracle: %v", err) | |||
| 107 | + | } | |||
| 108 | + | lines := strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") | |||
| 109 | + | if len(lines) != len(encodeTypeTests) { | |||
| 110 | + | t.Fatalf("oracle printed %d encodings; want %d", len(lines), len(encodeTypeTests)) | |||
| 111 | + | } | |||
| 112 | + | for i, tt := range encodeTypeTests { | |||
| 113 | + | if lines[i] != tt.want { | |||
| 114 | + | t.Errorf("@encode(%s) = %q; want %q", tt.cType, lines[i], tt.want) | |||
| 115 | + | } | |||
| 116 | + | } | |||
| 117 | + | } | |||
| 118 | + | ||||
| 119 | + | // TestEncodeFunc checks how encodeFunc assembles a method signature: the | |||
| 120 | + | // return type, the implicit self and _cmd parameters, and the argument order. | |||
| 121 | + | // encodeType is checked per type by TestEncodeType, so the cases here vary the | |||
| 122 | + | // shape of the signature rather than the types in it. The first case is the | |||
| 123 | + | // signature from issue #493, which was recorded as v@:LLLLLLLLS - declaring | |||
| 124 | + | // 64-bit arguments as 32-bit made NSInvocation and other consumers of the type | |||
| 125 | + | // encoding truncate values above 2^32. | |||
| 126 | + | func TestEncodeFunc(t *testing.T) { | |||
| 127 | + | tests := []struct { | |||
| 128 | + | name string | |||
| 129 | + | fn any | |||
| 130 | + | want string | |||
| 131 | + | }{ | |||
| 132 | + | { | |||
| 133 | + | name: "void return, 64-bit args", | |||
| 134 | + | fn: func(_ ID, _ SEL, a1, a2, a3, a4, a5, a6, a7, a8 uint64, a9 uint16) {}, | |||
| 135 | + | want: "v@:QQQQQQQQS", | |||
| 136 | + | }, | |||
| 137 | + | { | |||
| 138 | + | name: "value return, mixed integer kinds", | |||
| 139 | + | fn: func(_ ID, _ SEL, a int, b int64, c uint, d uint64) int { return 0 }, | |||
| 140 | + | want: "q@:qqQQ", | |||
| 141 | + | }, | |||
| 142 | + | { | |||
| 143 | + | name: "no arguments", | |||
| 144 | + | fn: func(_ ID, _ SEL) {}, | |||
| 145 | + | want: "v@:", | |||
| 146 | + | }, | |||
| 147 | + | { | |||
| 148 | + | name: "argument order is preserved", | |||
| 149 | + | fn: func(_ ID, _ SEL, a int8, b float64, c ID) Class { return 0 }, | |||
| 150 | + | want: "#@:cd@", | |||
| 151 | + | }, | |||
| 152 | + | } | |||
| 153 | + | for _, tt := range tests { | |||
| 154 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 155 | + | got, err := encodeFunc(tt.fn) | |||
| 156 | + | if err != nil { | |||
| 157 | + | t.Fatal(err) | |||
| 158 | + | } | |||
| 159 | + | if got != tt.want { | |||
| 160 | + | t.Errorf("encodeFunc = %q; want %q", got, tt.want) | |||
| 161 | + | } | |||
| 162 | + | }) | |||
| 163 | + | } | |||
| 164 | + | } | |||
| 165 | + | ||||
| 166 | + | func TestEncodeFuncErrors(t *testing.T) { | |||
| 167 | + | tests := []struct { | |||
| 168 | + | name string | |||
| 169 | + | fn any | |||
| 170 | + | }{ | |||
| 171 | + | {"not a func", 0}, | |||
| 172 | + | {"too many return values", func(_ ID, _ SEL) (int, int) { return 0, 0 }}, | |||
| 173 | + | {"missing self and _cmd", func() {}}, | |||
| 174 | + | {"missing _cmd", func(_ ID) {}}, | |||
| 175 | + | {"unencodable argument", func(_ ID, _ SEL, c chan int) {}}, | |||
| 176 | + | } | |||
| 177 | + | for _, tt := range tests { | |||
| 178 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 179 | + | if got, err := encodeFunc(tt.fn); err == nil { | |||
| 180 | + | t.Errorf("encodeFunc = %q; want an error", got) | |||
| 181 | + | } | |||
| 182 | + | }) | |||
| 183 | + | } | |||
| 184 | + | } | |||
M objc/objc_runtime_darwin.go +6 -6
| @@ -402,8 +402,8 @@ const ( | |||
| 402 | 402 | encUShort = "S" | |
| 403 | 403 | encInt = "i" | |
| 404 | 404 | encUInt = "I" | |
| 405 | - | encLong = "l" | |
| 406 | - | encULong = "L" | |
| 405 | + | encLongLong = "q" | |
| 406 | + | encULongLong = "Q" | |
| 407 | 407 | encFloat = "f" | |
| 408 | 408 | encDouble = "d" | |
| 409 | 409 | encBool = "B" | |
| @@ -432,7 +432,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { | |||
| 432 | 432 | case reflect.Bool: | |
| 433 | 433 | return encBool, nil | |
| 434 | 434 | case reflect.Int: | |
| 435 | - | return encLong, nil | |
| 435 | + | return encLongLong, nil | |
| 436 | 436 | case reflect.Int8: | |
| 437 | 437 | return encChar, nil | |
| 438 | 438 | case reflect.Int16: | |
| @@ -440,9 +440,9 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { | |||
| 440 | 440 | case reflect.Int32: | |
| 441 | 441 | return encInt, nil | |
| 442 | 442 | case reflect.Int64: | |
| 443 | - | return encULong, nil | |
| 443 | + | return encLongLong, nil | |
| 444 | 444 | case reflect.Uint: | |
| 445 | - | return encULong, nil | |
| 445 | + | return encULongLong, nil | |
| 446 | 446 | case reflect.Uint8: | |
| 447 | 447 | return encUChar, nil | |
| 448 | 448 | case reflect.Uint16: | |
| @@ -450,7 +450,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { | |||
| 450 | 450 | case reflect.Uint32: | |
| 451 | 451 | return encUInt, nil | |
| 452 | 452 | case reflect.Uint64: | |
| 453 | - | return encULong, nil | |
| 453 | + | return encULongLong, nil | |
| 454 | 454 | case reflect.Uintptr: | |
| 455 | 455 | return encPtr, nil | |
| 456 | 456 | case reflect.Float32: | |
| @@ -402,8 +402,8 @@ const ( | |||||
| 402 | encUShort = "S" | 402 | encUShort = "S" | ||
| 403 | encInt = "i" | 403 | encInt = "i" | ||
| 404 | encUInt = "I" | 404 | encUInt = "I" | ||
| 405 | - | encLong = "l" | 405 | + | encLongLong = "q" |
| 406 | - | encULong = "L" | 406 | + | encULongLong = "Q" |
| 407 | encFloat = "f" | 407 | encFloat = "f" | ||
| 408 | encDouble = "d" | 408 | encDouble = "d" | ||
| 409 | encBool = "B" | 409 | encBool = "B" | ||
| @@ -432,7 +432,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { | |||||
| 432 | case reflect.Bool: | 432 | case reflect.Bool: | ||
| 433 | return encBool, nil | 433 | return encBool, nil | ||
| 434 | case reflect.Int: | 434 | case reflect.Int: | ||
| 435 | - | return encLong, nil | 435 | + | return encLongLong, nil |
| 436 | case reflect.Int8: | 436 | case reflect.Int8: | ||
| 437 | return encChar, nil | 437 | return encChar, nil | ||
| 438 | case reflect.Int16: | 438 | case reflect.Int16: | ||
| @@ -440,9 +440,9 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { | |||||
| 440 | case reflect.Int32: | 440 | case reflect.Int32: | ||
| 441 | return encInt, nil | 441 | return encInt, nil | ||
| 442 | case reflect.Int64: | 442 | case reflect.Int64: | ||
| 443 | - | return encULong, nil | 443 | + | return encLongLong, nil |
| 444 | case reflect.Uint: | 444 | case reflect.Uint: | ||
| 445 | - | return encULong, nil | 445 | + | return encULongLong, nil |
| 446 | case reflect.Uint8: | 446 | case reflect.Uint8: | ||
| 447 | return encUChar, nil | 447 | return encUChar, nil | ||
| 448 | case reflect.Uint16: | 448 | case reflect.Uint16: | ||
| @@ -450,7 +450,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { | |||||
| 450 | case reflect.Uint32: | 450 | case reflect.Uint32: | ||
| 451 | return encUInt, nil | 451 | return encUInt, nil | ||
| 452 | case reflect.Uint64: | 452 | case reflect.Uint64: | ||
| 453 | - | return encULong, nil | 453 | + | return encULongLong, nil |
| 454 | case reflect.Uintptr: | 454 | case reflect.Uintptr: | ||
| 455 | return encPtr, nil | 455 | return encPtr, nil | ||
| 456 | case reflect.Float32: | 456 | case reflect.Float32: | ||