Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type Gen struct {
MaxArrayLength int // Default: 8192 (MaxLength)
MaxByteLength int // Default: 2<<20 (ByteArrayMaxLen)
MaxStringLength int // Default: 8192 (MaxLength)

// Write output file in order of type names
SortTypeNames bool
}

func (g Gen) maxArrayLength() int {
Expand Down Expand Up @@ -222,7 +225,15 @@ func nameIsExported(name string) bool {
}

func ParseTypeInfo(itype interface{}) (*GenTypeInfo, error) {
t := reflect.TypeOf(itype)
// If we're handed *Foo instead of value Foo, deref the pointer.
// ParseTypeInfo is only every handed a top level type, so this shouldn't violate any expectations.
iv := reflect.ValueOf(itype)
switch iv.Kind() {
case reflect.Pointer, reflect.Interface:
iv = iv.Elem()
default:
}
t := iv.Type()

pkg := t.PkgPath()

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

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

err := g.doTemplate(w, gti, `func (t *{{ .Name }}) MarshalCBOR(w io.Writer) error {
Expand Down
42 changes: 42 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"io"
"math"
"reflect"
"sort"
"sync"

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

return nil
}

// sort type example objects on name of type
func sortTypeNames(obs []any) []any {
temp := make([]tnAny, len(obs))
for i, ob := range obs {
v := reflect.ValueOf(ob)
if v.Kind() == reflect.Pointer {
v = v.Elem()
}
temp[i] = tnAny{v.Type().Name(), ob}
}
sortref := tnAnySorter(temp)
sort.Sort(&sortref)
out := make([]any, len(obs))
for i, rec := range temp {
out[i] = rec.ob
}
return out
}

// type-name and any
type tnAny struct {
name string
ob any
}

type tnAnySorter []tnAny

// sort.Interface
func (tas *tnAnySorter) Len() int {
return len(*tas)
}
func (tas *tnAnySorter) Less(i, j int) bool {
return (*tas)[i].name < (*tas)[j].name
}
func (tas *tnAnySorter) Swap(i, j int) {
t := (*tas)[i]
(*tas)[i] = (*tas)[j]
(*tas)[j] = t
}
24 changes: 24 additions & 0 deletions utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,27 @@ func (tr *testReader1Byte) Read(p []byte) (n int, err error) {
tr.emptied = true
return 1, io.EOF
}

type TTA struct{}
type TTA_B struct{}
type TTB struct{}

func TestTypeSorter(t *testing.T) {
sortedTypes := sortTypeNames([]any{
TTA_B{},
TTB{},
TTA{},
})
_, ok := sortedTypes[0].(TTA)
if !ok {
t.Errorf("wanted [0]TTA, got %T", sortedTypes[0])
}
_, ok = sortedTypes[1].(TTA_B)
if !ok {
t.Errorf("wanted [0]TTA_B, got %T", sortedTypes[1])
}
_, ok = sortedTypes[2].(TTB)
if !ok {
t.Errorf("wanted [0]TTB, got %T", sortedTypes[2])
}
}
10 changes: 8 additions & 2 deletions writefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ func WriteTupleEncodersToFile(fname, pkg string, types ...interface{}) error {
// The MarshalCBOR and UnmarshalCBOR implementations will marshal/unmarshal each type's fields as a
// fixed-length CBOR array of field values.
func (g Gen) WriteTupleEncodersToFile(fname, pkg string, types ...interface{}) error {
if g.SortTypeNames {
types = sortTypeNames(types)
}
buf := new(bytes.Buffer)

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

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

for _, t := range typeInfos {
for i, t := range typeInfos {
if err := g.GenMapEncodersForType(t, buf); err != nil {
return xerrors.Errorf("failed to generate encoders: %w", err)
return xerrors.Errorf("%T (%s) failed to generate encoders: %w", types[i], t.Name, err)
}
}

Expand Down