Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
14 changes: 14 additions & 0 deletions _generated/custom_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package _generated

//go:generate msgp -d "tags primary,fallback"

type CustomTags struct {
Field1 string `primary:"f1_primary"`
Field2 string `fallback:"f2_fallback"`
Field3 string `primary:"f3_primary" fallback:"f3_fallback_ignored"`
Field4 string `msg:"f4_msg"`
Field5 string `msgpack:"f5_msgpack"`
Field6 string `fallback:"f6_fallback" msg:"f6_msg_ignored"`
Field7 string `fallback:"f7_fallback" msgpack:"f7_msgpack_ignored"`
Field8 string `primary:"f8_primary" msg:"f8_msg_ignored" msgpack:"f8_msgpack_ignored"`
}
93 changes: 93 additions & 0 deletions _generated/custom_tags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package _generated

import (
"bytes"
"encoding/json"
"reflect"
"testing"

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

func TestCustomTags(t *testing.T) {
ts := CustomTags{
Field1: "v1",
Field2: "v2",
Field3: "v3",
Field4: "v4",
Field5: "v5",
Field6: "v6",
Field7: "v7",
Field8: "v8",
}
wantKeys := map[string]any{
"f1_primary": "v1",
"f2_fallback": "v2",
"f3_primary": "v3",
"f4_msg": "v4",
"f5_msgpack": "v5",
"f6_fallback": "v6",
"f7_fallback": "v7",
"f8_primary": "v8",
}

t.Run("EncodeDecode", func(t *testing.T) {
var b bytes.Buffer
if err := msgp.Encode(&b, &ts); err != nil {
t.Fatal(err)
}
var got CustomTags
if err := msgp.Decode(&b, &got); err != nil {
t.Fatal(err)
}
if got != ts {
t.Errorf("got %+v, want %+v", got, ts)
}
})

t.Run("MarshalUnmarshal", func(t *testing.T) {
buf, err := ts.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
var got CustomTags
left, err := got.UnmarshalMsg(buf)
if err != nil {
t.Fatal(err)
}
if len(left) != 0 {
t.Errorf("%d bytes left after unmarshal", len(left))
}
if got != ts {
t.Errorf("got %+v, want %+v", got, ts)
}
})

t.Run("WireKeys", func(t *testing.T) {
buf, err := ts.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
var jsonBuf bytes.Buffer
if _, err := msgp.UnmarshalAsJSON(&jsonBuf, buf); err != nil {
t.Fatal(err)
}
got := map[string]any{}
if err := json.Unmarshal(jsonBuf.Bytes(), &got); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, wantKeys) {
t.Errorf("got %v, want %v", got, wantKeys)
}
})

t.Run("Msgsize", func(t *testing.T) {
buf, err := ts.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
if est := ts.Msgsize(); est < len(buf) {
t.Errorf("Msgsize %d underestimates actual %d", est, len(buf))
}
})
}
23 changes: 20 additions & 3 deletions parse/directives.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var directives = map[string]directive{
// and then add it to this list.
var earlyDirectives = map[string]directive{
"tag": tag,
"tags": tag,
"pointer": pointer,
"maps": maps,
}
Expand Down Expand Up @@ -237,12 +238,28 @@ func asvartuple(text []string, f *FileSet) error {
}

//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.
func tag(text []string, f *FileSet) error {
if len(text) != 2 {
if len(text) < 2 {
return nil
}
var names []string
for _, t := range text[1:] {
for _, n := range strings.Split(t, ",") {
Comment thread
klauspost marked this conversation as resolved.
Outdated
if n = strings.TrimSpace(n); n != "" {
names = append(names, n)
}
}
}
if len(names) == 0 {
return nil
}
f.tagName = strings.TrimSpace(text[1])
infof("using field tag %q\n", f.tagName)
f.tagNames = names
infof("using field tag %q\n", names)
Comment thread
klauspost marked this conversation as resolved.
Outdated
return nil
}

Expand Down
15 changes: 9 additions & 6 deletions parse/getast.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ type FileSet struct {
NoDuplicates bool // Reject duplicate keys for all types
NoDupTypes map[string]struct{} // Reject duplicate keys for specific types only

tagName string // tag to read field names from
pointerRcv bool // generate with pointer receivers.
tagNames []string // tags to read field names from, in priority order
pointerRcv bool // generate with pointer receivers.
}

// File parses a file at the relative path
Expand Down Expand Up @@ -527,15 +527,18 @@ func (fs *FileSet) getField(f *ast.Field) []gen.StructField {
var extension, flatten bool
// parse tag; otherwise field name is field tag
if f.Tag != nil {
st := reflect.StructTag(strings.Trim(f.Tag.Value, "`"))
var body string
if fs.tagName != "" {
body = reflect.StructTag(strings.Trim(f.Tag.Value, "`")).Get(fs.tagName)
for _, name := range fs.tagNames {
if body = st.Get(name); body != "" {
break
}
}
if body == "" {
Comment thread
klauspost marked this conversation as resolved.
Outdated
body = reflect.StructTag(strings.Trim(f.Tag.Value, "`")).Get("msg")
body = st.Get("msg")
}
if body == "" {
body = reflect.StructTag(strings.Trim(f.Tag.Value, "`")).Get("msgpack")
body = st.Get("msgpack")
}
tags := strings.Split(body, ",")
if len(tags) >= 2 {
Expand Down
Loading