Skip to content

Commit

Permalink
struct marshaler
Browse files Browse the repository at this point in the history
  • Loading branch information
Songmu committed Jul 10, 2016
1 parent b7f2c59 commit 46c0730
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 3 deletions.
62 changes: 59 additions & 3 deletions encode.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package ltsv

import (
"encoding"
"fmt"
"reflect"
"strconv"
"strings"
)

type Marshaler interface {
MarshalLTSV([]byte) error
MarshalLTSV() ([]byte, error)
}

// MarshalError is an error type for Marshal()
Expand Down Expand Up @@ -39,7 +41,7 @@ type MarshalTypeError struct {
}

func (e *MarshalTypeError) Error() string {
return "ltsv: cannot marshal " + e.Value + " into Go value of type " + e.Type.String()
return "ltsv: cannot marshal Go value " + e.Value + " of type " + e.Type.String() + " into ltsv"
}

func Marshal(v interface{}) ([]byte, error) {
Expand All @@ -65,5 +67,59 @@ func Marshal(v interface{}) ([]byte, error) {
}
return []byte(strings.Join(arr, "\t")), nil
}
return nil, nil

t := rv.Type()
numField := t.NumField()
arr := make([]string, 0, numField)
errs := MarshalError{}
for i := 0; i < numField; i++ {
ft := t.Field(i)
fv := rv.Field(i)
tag := ft.Tag.Get("ltsv")
tags := strings.Split(tag, ",")
key := tags[0]
if key == "-" {
continue
}
if key == "" {
key = strings.ToLower(ft.Name)
}

switch fv.Kind() {
case reflect.String:
arr = append(arr, key+":"+fv.String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
arr = append(arr, key+":"+strconv.FormatInt(fv.Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
arr = append(arr, key+":"+strconv.FormatUint(fv.Uint(), 10))
case reflect.Float32, reflect.Float64:
arr = append(arr, key+":"+strconv.FormatFloat(fv.Float(), 'f', -1, fv.Type().Bits()))
case reflect.Interface:
if u, ok := fv.Interface().(Marshaler); ok {
buf, err := u.MarshalLTSV()
if err != nil {
errs[ft.Name] = err
} else {
arr = append(arr, key+":"+string(buf))
}
continue
}
if u, ok := fv.Interface().(encoding.TextMarshaler); ok {
buf, err := u.MarshalText()
if err != nil {
errs[ft.Name] = err
} else {
arr = append(arr, key+":"+string(buf))
}
continue
}
fallthrough
default:
errs[ft.Name] = &MarshalTypeError{fv.String(), fv.Type()}
}
}
if len(errs) < 1 {
return []byte(strings.Join(arr, "\t")), nil
}
return nil, errs
}
20 changes: 20 additions & 0 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,24 @@ func TestMarshal(t *testing.T) {
if string(r) != string(expect1) && string(r) != string(expect2) {
t.Errorf("result is not expected: %s", string(r))
}

type ss struct {
User string `ltsv:"user"`
Age uint8 `ltsv:"age"`
Height float64 `ltsv:"height"`
Weight float32
Memo string `ltsv:"-"`
}
s := &ss{
User: "songmu",
Age: 36,
Height: 169.1,
Weight: 66.6,
Memo: "songmu.jp",
}
expect := []byte("user:songmu\tage:36\theight:169.1\tweight:66.6")
buf, _ := Marshal(s)
if string(buf) != string(expect) {
t.Errorf("result is not expected: %s", string(buf))
}
}

0 comments on commit 46c0730

Please sign in to comment.