From f5b7a366095d6046a356d6163af4108e7f6024e5 Mon Sep 17 00:00:00 2001 From: Ian Lopshire Date: Fri, 23 Aug 2019 16:24:48 -0400 Subject: [PATCH] move struct spec logic into tags file --- encode.go | 36 ------------------------------------ tags.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/encode.go b/encode.go index 2fcfa0a..64911f2 100644 --- a/encode.go +++ b/encode.go @@ -7,7 +7,6 @@ import ( "io" "reflect" "strconv" - "sync" ) // Marshal returns the fixed-width encoding of v. @@ -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() } diff --git a/tags.go b/tags.go index ba54e2d..71a2a04 100644 --- a/tags.go +++ b/tags.go @@ -1,8 +1,10 @@ package fixedwidth import ( + "reflect" "strconv" "strings" + "sync" ) // parseTag splits a struct fields fixed tag into its start and end positions. @@ -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) +}