Skip to content

Commit

Permalink
move struct spec logic into tags file
Browse files Browse the repository at this point in the history
  • Loading branch information
ianlopshire committed Aug 23, 2019
1 parent fb049b5 commit f5b7a36
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 36 deletions.
36 changes: 0 additions & 36 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"io"
"reflect"
"strconv"
"sync"
)

// Marshal returns the fixed-width encoding of v.
Expand Down Expand Up @@ -166,41 +165,6 @@ func structEncoder(v reflect.Value) ([]byte, error) {
return dst, nil
}

type structSpec struct {
ll int
fieldSpecs []fieldSpec
}

type fieldSpec struct {
startPos, endPos int
ok bool
}

func buildStructSpec(t reflect.Type) structSpec {
ss := structSpec{
fieldSpecs: make([]fieldSpec, t.NumField()),
}
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
ss.fieldSpecs[i].startPos, ss.fieldSpecs[i].endPos, ss.fieldSpecs[i].ok = parseTag(f.Tag.Get("fixed"))
if ss.fieldSpecs[i].endPos > ss.ll {
ss.ll = ss.fieldSpecs[i].endPos
}
}
return ss
}

var fieldSpecCache sync.Map // map[reflect.Type]structSpec

// cachedStructSpec is like buildStructSpec but cached to prevent duplicate work.
func cachedStructSpec(t reflect.Type) structSpec {
if f, ok := fieldSpecCache.Load(t); ok {
return f.(structSpec)
}
f, _ := fieldSpecCache.LoadOrStore(t, buildStructSpec(t))
return f.(structSpec)
}

func textMarshalerEncoder(v reflect.Value) ([]byte, error) {
return v.Interface().(encoding.TextMarshaler).MarshalText()
}
Expand Down
38 changes: 38 additions & 0 deletions tags.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package fixedwidth

import (
"reflect"
"strconv"
"strings"
"sync"
)

// parseTag splits a struct fields fixed tag into its start and end positions.
Expand All @@ -26,3 +28,39 @@ func parseTag(tag string) (startPos, endPos int, ok bool) {

return startPos, endPos, true
}

type structSpec struct {
// ll is the line length for the struct
ll int
fieldSpecs []fieldSpec
}

type fieldSpec struct {
startPos, endPos int
ok bool
}

func buildStructSpec(t reflect.Type) structSpec {
ss := structSpec{
fieldSpecs: make([]fieldSpec, t.NumField()),
}
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
ss.fieldSpecs[i].startPos, ss.fieldSpecs[i].endPos, ss.fieldSpecs[i].ok = parseTag(f.Tag.Get("fixed"))
if ss.fieldSpecs[i].endPos > ss.ll {
ss.ll = ss.fieldSpecs[i].endPos
}
}
return ss
}

var fieldSpecCache sync.Map // map[reflect.Type]structSpec

// cachedStructSpec is like buildStructSpec but cached to prevent duplicate work.
func cachedStructSpec(t reflect.Type) structSpec {
if f, ok := fieldSpecCache.Load(t); ok {
return f.(structSpec)
}
f, _ := fieldSpecCache.LoadOrStore(t, buildStructSpec(t))
return f.(structSpec)
}

0 comments on commit f5b7a36

Please sign in to comment.