Skip to content
Open
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
36 changes: 36 additions & 0 deletions _generated/named_shim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package _generated

//go:generate msgp

//msgp:shim *NamedShimOriginal as:NamedShimWire using:namedShimToWire/NamedShimFromWire
//msgp:ignore NamedShimOriginal

// The original type has promoted string serializers. The shim must use the
// generated map serializer instead, including when decoding into a zero value.
type NamedShimOriginal struct {
NamedShimString
}

type NamedShimString string

type NamedShimWire struct {
Value *string
}

func namedShimToWire(v *NamedShimOriginal) *NamedShimWire {
return &NamedShimWire{Value: (*string)(&v.NamedShimString)}
}

// NamedShimFromWire is the inverse of namedShimToWire.
func NamedShimFromWire(v *NamedShimWire) *NamedShimOriginal {
return &NamedShimOriginal{NamedShimString: NamedShimString(*v.Value)}
}

type NamedShimContainer struct {
Value NamedShimOriginal
Pointer *NamedShimOriginal
Plain NamedShimString
Slice []NamedShimOriginal
Array [1]NamedShimOriginal
Map map[string]NamedShimOriginal
}
128 changes: 128 additions & 0 deletions _generated/named_shim_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package _generated

import (
"bytes"
"reflect"
"testing"

"github.com/tinylib/msgp/msgp"
)

func TestNamedShim(t *testing.T) {
for _, pointer := range []*NamedShimOriginal{nil, {NamedShimString: "pointer"}} {
name := "pointer"
if pointer == nil {
name = "nil pointer"
}
t.Run(name, func(t *testing.T) {
in := NamedShimContainer{
Value: NamedShimOriginal{NamedShimString: "value"},
Pointer: pointer,
Plain: "plain",
Slice: []NamedShimOriginal{{NamedShimString: "slice"}},
Array: [1]NamedShimOriginal{{NamedShimString: "array"}},
Map: map[string]NamedShimOriginal{"key": {NamedShimString: "map"}},
}
// Assemble the expected map encoding independently of generated methods.
want := msgp.AppendMapHeader(nil, 6)
want = msgp.AppendString(want, "Value")
want = msgp.AppendMapHeader(want, 1)
want = msgp.AppendString(want, "Value")
want = msgp.AppendString(want, "value")
want = msgp.AppendString(want, "Pointer")
if pointer == nil {
want = msgp.AppendNil(want)
} else {
want = msgp.AppendMapHeader(want, 1)
want = msgp.AppendString(want, "Value")
want = msgp.AppendString(want, "pointer")
}
want = msgp.AppendString(want, "Plain")
want = msgp.AppendString(want, "plain")
for _, field := range []struct{ name, value string }{{"Slice", "slice"}, {"Array", "array"}} {
want = msgp.AppendString(want, field.name)
want = msgp.AppendArrayHeader(want, 1)
want = msgp.AppendMapHeader(want, 1)
want = msgp.AppendString(want, "Value")
want = msgp.AppendString(want, field.value)
}
want = msgp.AppendString(want, "Map")
want = msgp.AppendMapHeader(want, 1)
want = msgp.AppendString(want, "key")
want = msgp.AppendMapHeader(want, 1)
want = msgp.AppendString(want, "Value")
want = msgp.AppendString(want, "map")

t.Run("MarshalMsg", func(t *testing.T) {
got, err := in.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(got, want) {
t.Fatalf("encoding = %x, want %x", got, want)
}
})
t.Run("EncodeMsg", func(t *testing.T) {
var buf bytes.Buffer
writer := msgp.NewWriter(&buf)
if err := in.EncodeMsg(writer); err != nil {
t.Fatal(err)
}
if err := writer.Flush(); err != nil {
t.Fatal(err)
}
if !bytes.Equal(buf.Bytes(), want) {
t.Fatalf("encoding = %x, want %x", buf.Bytes(), want)
}
})
t.Run("UnmarshalMsg", func(t *testing.T) {
var out NamedShimContainer
left, err := out.UnmarshalMsg(want)
if err != nil {
t.Fatal(err)
}
if len(left) != 0 || !reflect.DeepEqual(out, in) {
t.Fatalf("decoded %#v with %x left, want %#v", out, left, in)
}
})
t.Run("DecodeMsg", func(t *testing.T) {
var out NamedShimContainer
if err := out.DecodeMsg(msgp.NewReader(bytes.NewReader(want))); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(out, in) {
t.Fatalf("decoded %#v, want %#v", out, in)
}
})
t.Run("Msgsize", func(t *testing.T) {
if got := in.Msgsize(); got < len(want) {
t.Fatalf("Msgsize %d under-reports wire size %d", got, len(want))
}
})
})
}
}

func TestNamedShimDecodeError(t *testing.T) {
// Valid MessagePack with a boolean where the named serializer expects a string.
data := msgp.AppendMapHeader(nil, 1)
data = msgp.AppendString(data, "Value")
data = msgp.AppendMapHeader(data, 1)
data = msgp.AppendString(data, "Value")
data = msgp.AppendBool(data, true)

t.Run("UnmarshalMsg", func(t *testing.T) {
var out NamedShimContainer
_, err := out.UnmarshalMsg(data)
if cause, ok := msgp.Cause(err).(msgp.TypeError); !ok || cause.Method != msgp.StrType || cause.Encoded != msgp.BoolType {
t.Fatalf("expected string/boolean type error, got %v", err)
}
})
t.Run("DecodeMsg", func(t *testing.T) {
var out NamedShimContainer
err := out.DecodeMsg(msgp.NewReader(bytes.NewReader(data)))
if cause, ok := msgp.Cause(err).(msgp.TypeError); !ok || cause.Method != msgp.StrType || cause.Encoded != msgp.BoolType {
t.Fatalf("expected string/boolean type error, got %v", err)
}
})
}
11 changes: 8 additions & 3 deletions parse/directives.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ func applyShim(text []string, f *FileSet) error {
text = text[1:]
}

// Named cast shims must call the serializer returned by the conversion.
if be.Value == gen.IDENT && be.ShimMode == gen.Cast {
be.Convert = true
}

infof("%s -> %s\n", name, be.Value.String())
f.findShim(name, be, true)

Expand Down Expand Up @@ -237,12 +242,12 @@ func asvartuple(text []string, f *FileSet) error {
return nil
}

//msgp:tag {tagname}
//msgp:tags {tag1},{tag2},...
//
// The tag/tags directive accepts a comma-separated priority list; fields are
// read from the first tag that has a non-empty value, falling back to msg
// then msgpack if none of the listed tags match.
//
//msgp:tag {tagname}
//msgp:tags {tag1},{tag2},...
func tag(text []string, f *FileSet) error {
if len(text) < 2 {
return nil
Expand Down
Loading