now marshaller respects options like 'omitempty'
This commit is contained in:
parent
058076e94f
commit
e27d7cfab2
3 changed files with 71 additions and 3 deletions
|
@ -424,7 +424,7 @@ func bencodeKey(field reflect.StructField) (key string) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
return key
|
||||
}
|
||||
|
||||
func writeStruct(w io.Writer, val reflect.Value) (err error) {
|
||||
|
@ -440,7 +440,11 @@ func writeStruct(w io.Writer, val reflect.Value) (err error) {
|
|||
|
||||
for i := 0; i < numFields; i++ {
|
||||
field := typ.Field(i)
|
||||
svList[i].key = bencodeKey(field)
|
||||
key, opts := parseTag(bencodeKey(field))
|
||||
if key == "-" || opts.Contains("omitempty") && isEmptyValue(val.Field(i)) {
|
||||
continue
|
||||
}
|
||||
svList[i].key = key
|
||||
svList[i].value = val.Field(i)
|
||||
}
|
||||
|
||||
|
@ -456,6 +460,59 @@ func writeStruct(w io.Writer, val reflect.Value) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func writeValue(w io.Writer, val reflect.Value) (err error) {
|
||||
if !val.IsValid() {
|
||||
err = errors.New("Can't write null value")
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package bencode
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testStruct struct {
|
||||
Field1 string `bencode:"my field1"`
|
||||
Field2 int64 `bencode:"my field2"`
|
||||
Field3 int64 `bencode:"my field3,omitempty"`
|
||||
}
|
||||
|
||||
type testOldTag struct {
|
||||
|
@ -15,12 +17,16 @@ type testOldTag struct {
|
|||
}
|
||||
|
||||
func TestMarshalling(t *testing.T) {
|
||||
ts1 := testStruct{"foo", 123456}
|
||||
ts1 := testStruct{Field1: "foo", Field2: 123456}
|
||||
buf, err := Marshal(ts1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if bytes.Contains(buf, []byte("omitempty")) || bytes.Contains(buf, []byte("field3")) {
|
||||
t.Errorf("should not have the string 'omitempty' or 'field3' in %q", buf)
|
||||
}
|
||||
|
||||
ts2 := testStruct{}
|
||||
err = Unmarshal(buf, &ts2)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package torrent
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/vbatts/go-bt/bencode"
|
||||
"testing"
|
||||
)
|
||||
|
@ -19,6 +20,10 @@ func TestFileMarshal(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if bytes.Contains(buf, []byte("omitempty")) || bytes.Contains(buf, []byte("created by")) {
|
||||
t.Errorf("should not have the string 'omitempty' or 'created by' in %q", buf)
|
||||
}
|
||||
|
||||
f2 := File{}
|
||||
err = bencode.Unmarshal(buf, &f2)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue