diff --git a/gen.go b/gen.go index ed2bf24..029682e 100644 --- a/gen.go +++ b/gen.go @@ -69,10 +69,11 @@ var _ = xerrors.Errorf } type Field struct { - Name string - Pointer bool - Type reflect.Type - Pkg string + Name string + Serialized string + Pointer bool + Type reflect.Type + Pkg string IterLabel string } @@ -189,11 +190,16 @@ func ParseTypeInfo(i interface{}) (*GenTypeInfo, error) { pointer = true } + serialized, hasSerialized := f.Tag.Lookup("json") + if !hasSerialized { + serialized = f.Name + } out.Fields = append(out.Fields, Field{ - Name: f.Name, - Pointer: pointer, - Type: ft, - Pkg: pkg, + Name: f.Name, + Serialized: serialized, + Pointer: pointer, + Type: ft, + Pkg: pkg, }) } @@ -1124,7 +1130,7 @@ func emitCborMarshalStructMap(w io.Writer, gti *GenTypeInfo) error { fmt.Fprintf(w, "\n\t// t.%s (%s) (%s)", f.Name, f.Type, f.Type.Kind()) if err := emitCborMarshalStringField(w, Field{ - Name: `"` + f.Name + `"`, + Name: `"` + f.Serialized + `"`, }); err != nil { return err } @@ -1219,7 +1225,7 @@ func (t *{{ .Name}}) UnmarshalCBOR(r io.Reader) error { fmt.Fprintf(w, "// t.%s (%s) (%s)", f.Name, f.Type, f.Type.Kind()) err := doTemplate(w, f, ` - case "{{ .Name }}": + case "{{ .Serialized }}": `) if err != nil { return err diff --git a/testgen/main.go b/testgen/main.go index acf5be4..f7b3701 100644 --- a/testgen/main.go +++ b/testgen/main.go @@ -20,6 +20,7 @@ func main() { if err := cbg.WriteMapEncodersToFile("testing/cbor_map_gen.go", "testing", types.SimpleTypeTree{}, types.NeedScratchForMap{}, + types.MapWithRenames{}, ); err != nil { panic(err) } diff --git a/testing/cbor_map_gen.go b/testing/cbor_map_gen.go index 1009d6f..b12a15c 100644 --- a/testing/cbor_map_gen.go +++ b/testing/cbor_map_gen.go @@ -496,3 +496,168 @@ func (t *NeedScratchForMap) UnmarshalCBOR(r io.Reader) error { return nil } +func (t *MapWithRenames) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{163}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.String (string) (string) + if len("s") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"s\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("s"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("s")); err != nil { + return err + } + + if len(t.String) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.String was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.String))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.String)); err != nil { + return err + } + + // t.Int (uint64) (uint64) + if len("i") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"i\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("i"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("i")); err != nil { + return err + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Int)); err != nil { + return err + } + + // t.Bytes ([]uint8) (slice) + if len("b") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"b\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("b"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("b")); err != nil { + return err + } + + if len(t.Bytes) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field t.Bytes was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.Bytes))); err != nil { + return err + } + + if _, err := w.Write(t.Bytes[:]); err != nil { + return err + } + return nil +} + +func (t *MapWithRenames) UnmarshalCBOR(r io.Reader) error { + *t = MapWithRenames{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("MapWithRenames: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.String (string) (string) + case "s": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.String = string(sval) + } + // t.Int (uint64) (uint64) + case "i": + + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Int = uint64(extra) + + } + // t.Bytes ([]uint8) (slice) + case "b": + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Bytes: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Bytes = make([]uint8, extra) + } + + if _, err := io.ReadFull(br, t.Bytes[:]); err != nil { + return err + } + + default: + return fmt.Errorf("unknown struct field %d: '%s'", i, name) + } + } + + return nil +} diff --git a/testing/roundtrip_test.go b/testing/roundtrip_test.go index fed37c6..965a89f 100644 --- a/testing/roundtrip_test.go +++ b/testing/roundtrip_test.go @@ -43,6 +43,10 @@ func TestNeedScratchForMap(t *testing.T) { testTypeRoundtrips(t, reflect.TypeOf(NeedScratchForMap{})) } +func TestMapWithRenames(t *testing.T) { + testTypeRoundtrips(t, reflect.TypeOf(MapWithRenames{})) +} + func testValueRoundtrip(t *testing.T, obj cbg.CBORMarshaler, nobj cbg.CBORUnmarshaler) { buf := new(bytes.Buffer) diff --git a/testing/types.go b/testing/types.go index 58a8d2c..06a22ed 100644 --- a/testing/types.go +++ b/testing/types.go @@ -65,3 +65,9 @@ type ThingWithSomeTime struct { type NeedScratchForMap struct { Thing bool } + +type MapWithRenames struct { + String string `json:"s"` + Int uint64 `json:"i"` + Bytes []byte `json:"b"` +}