Skip to content

Commit 6dace5a

Browse files
Merge pull request #102 from brianolson/sort-type-names
optionally sort type names in generated code file
2 parents 74d7464 + 5189b25 commit 6dace5a

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

gen.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ type Gen struct {
3232
MaxArrayLength int // Default: 8192 (MaxLength)
3333
MaxByteLength int // Default: 2<<20 (ByteArrayMaxLen)
3434
MaxStringLength int // Default: 8192 (MaxLength)
35+
36+
// Write output file in order of type names
37+
SortTypeNames bool
3538
}
3639

3740
func (g Gen) maxArrayLength() int {
@@ -222,7 +225,15 @@ func nameIsExported(name string) bool {
222225
}
223226

224227
func ParseTypeInfo(itype interface{}) (*GenTypeInfo, error) {
225-
t := reflect.TypeOf(itype)
228+
// If we're handed *Foo instead of value Foo, deref the pointer.
229+
// ParseTypeInfo is only every handed a top level type, so this shouldn't violate any expectations.
230+
iv := reflect.ValueOf(itype)
231+
switch iv.Kind() {
232+
case reflect.Pointer, reflect.Interface:
233+
iv = iv.Elem()
234+
default:
235+
}
236+
t := iv.Type()
226237

227238
pkg := t.PkgPath()
228239

@@ -1683,7 +1694,7 @@ func (g Gen) emitCborMarshalStructMap(w io.Writer, gti *GenTypeInfo) error {
16831694
}
16841695

16851696
if gti.Transparent {
1686-
return fmt.Errorf("transparent fields not supported in map mode, use tuple encoding (outcome should be the same)")
1697+
return fmt.Errorf("%#v: transparent fields not supported in map mode, use tuple encoding (outcome should be the same)", gti.Name)
16871698
}
16881699

16891700
err := g.doTemplate(w, gti, `func (t *{{ .Name }}) MarshalCBOR(w io.Writer) error {

utils.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"fmt"
88
"io"
99
"math"
10+
"reflect"
11+
"sort"
1012
"sync"
1113

1214
cid "github.com/ipfs/go-cid"
@@ -487,3 +489,43 @@ func WriteCidBuf(buf []byte, w io.Writer, c cid.Cid) error {
487489

488490
return nil
489491
}
492+
493+
// sort type example objects on name of type
494+
func sortTypeNames(obs []any) []any {
495+
temp := make([]tnAny, len(obs))
496+
for i, ob := range obs {
497+
v := reflect.ValueOf(ob)
498+
if v.Kind() == reflect.Pointer {
499+
v = v.Elem()
500+
}
501+
temp[i] = tnAny{v.Type().Name(), ob}
502+
}
503+
sortref := tnAnySorter(temp)
504+
sort.Sort(&sortref)
505+
out := make([]any, len(obs))
506+
for i, rec := range temp {
507+
out[i] = rec.ob
508+
}
509+
return out
510+
}
511+
512+
// type-name and any
513+
type tnAny struct {
514+
name string
515+
ob any
516+
}
517+
518+
type tnAnySorter []tnAny
519+
520+
// sort.Interface
521+
func (tas *tnAnySorter) Len() int {
522+
return len(*tas)
523+
}
524+
func (tas *tnAnySorter) Less(i, j int) bool {
525+
return (*tas)[i].name < (*tas)[j].name
526+
}
527+
func (tas *tnAnySorter) Swap(i, j int) {
528+
t := (*tas)[i]
529+
(*tas)[i] = (*tas)[j]
530+
(*tas)[j] = t
531+
}

utils_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,27 @@ func (tr *testReader1Byte) Read(p []byte) (n int, err error) {
226226
tr.emptied = true
227227
return 1, io.EOF
228228
}
229+
230+
type TTA struct{}
231+
type TTA_B struct{}
232+
type TTB struct{}
233+
234+
func TestTypeSorter(t *testing.T) {
235+
sortedTypes := sortTypeNames([]any{
236+
TTA_B{},
237+
TTB{},
238+
TTA{},
239+
})
240+
_, ok := sortedTypes[0].(TTA)
241+
if !ok {
242+
t.Errorf("wanted [0]TTA, got %T", sortedTypes[0])
243+
}
244+
_, ok = sortedTypes[1].(TTA_B)
245+
if !ok {
246+
t.Errorf("wanted [0]TTA_B, got %T", sortedTypes[1])
247+
}
248+
_, ok = sortedTypes[2].(TTB)
249+
if !ok {
250+
t.Errorf("wanted [0]TTB, got %T", sortedTypes[2])
251+
}
252+
}

writefile.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ func WriteTupleEncodersToFile(fname, pkg string, types ...interface{}) error {
2121
// The MarshalCBOR and UnmarshalCBOR implementations will marshal/unmarshal each type's fields as a
2222
// fixed-length CBOR array of field values.
2323
func (g Gen) WriteTupleEncodersToFile(fname, pkg string, types ...interface{}) error {
24+
if g.SortTypeNames {
25+
types = sortTypeNames(types)
26+
}
2427
buf := new(bytes.Buffer)
2528

2629
typeInfos := make([]*GenTypeInfo, len(types))
@@ -74,6 +77,9 @@ func WriteMapEncodersToFile(fname, pkg string, types ...interface{}) error {
7477
// The MarshalCBOR and UnmarshalCBOR implementations will marshal/unmarshal each type's fields as a
7578
// map of field names to field values.
7679
func (g Gen) WriteMapEncodersToFile(fname, pkg string, types ...interface{}) error {
80+
if g.SortTypeNames {
81+
types = sortTypeNames(types)
82+
}
7783
buf := new(bytes.Buffer)
7884

7985
typeInfos := make([]*GenTypeInfo, len(types))
@@ -89,9 +95,9 @@ func (g Gen) WriteMapEncodersToFile(fname, pkg string, types ...interface{}) err
8995
return xerrors.Errorf("failed to write header: %w", err)
9096
}
9197

92-
for _, t := range typeInfos {
98+
for i, t := range typeInfos {
9399
if err := g.GenMapEncodersForType(t, buf); err != nil {
94-
return xerrors.Errorf("failed to generate encoders: %w", err)
100+
return xerrors.Errorf("%T (%s) failed to generate encoders: %w", types[i], t.Name, err)
95101
}
96102
}
97103

0 commit comments

Comments
 (0)