summaryrefslogtreecommitdiff
path: root/rrdformat/rrdbinary/unmarshal.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2020-01-27 19:35:32 -0500
committerLuke Shumaker <lukeshu@lukeshu.com>2020-01-27 19:35:32 -0500
commita047b135ca416584178a6adde64cc156ab637431 (patch)
treeeffbe114ece44bb30fa73c73ff25de98fcaa5fb2 /rrdformat/rrdbinary/unmarshal.go
parent496fca7357463f6ca05acab688018e8a1dc11855 (diff)
Have RRD.UnmarshalBinary() avoid parsing things repeatedly
Diffstat (limited to 'rrdformat/rrdbinary/unmarshal.go')
-rw-r--r--rrdformat/rrdbinary/unmarshal.go305
1 files changed, 0 insertions, 305 deletions
diff --git a/rrdformat/rrdbinary/unmarshal.go b/rrdformat/rrdbinary/unmarshal.go
deleted file mode 100644
index 00f1222..0000000
--- a/rrdformat/rrdbinary/unmarshal.go
+++ /dev/null
@@ -1,305 +0,0 @@
-package rrdbinary
-
-import (
- "bytes"
- "fmt"
- "math"
- "reflect"
- "strconv"
- "strings"
-)
-
-type Decoder struct {
- arch Architecture
- pos int
- data []byte
-}
-
-type unmarshaler interface {
- unmarshalRRD(d *Decoder, tag string) error
-}
-
-func Unmarshal(arch Architecture, data []byte, ptr interface{}) error {
- ptrValue := reflect.ValueOf(ptr)
- if ptrValue.Kind() != reflect.Ptr {
- return typeErrorf("ptr is a %v, not a pointer", ptrValue.Kind())
- }
- decoder := &Decoder{
- arch: arch,
- pos: 0,
- data: data,
- }
- return decoder.Decode(ptrValue, "")
-}
-
-func (d *Decoder) binError(ctxLen int, msg string) error {
- return NewBinError(msg, d.data, d.pos, ctxLen)
-}
-
-func (d *Decoder) binErrorf(ctxLen int, format string, a ...interface{}) error {
- return d.binError(ctxLen, fmt.Sprintf(format, a...))
-}
-
-func (d *Decoder) Decode(v reflect.Value, tag string) error {
- if v.CanInterface() {
- if u, ok := v.Interface().(unmarshaler); ok {
- return u.unmarshalRRD(d, tag)
- }
- }
- switch v.Type().Kind() {
- case reflect.Struct:
- return d.decodeStruct(v, tag)
- case reflect.Array, reflect.Slice:
- return d.decodeList(v, tag)
- default:
- return typeErrorf("invalid type for rrdbinary.Decoder.Decode: %v", v.Type())
- }
-}
-
-func (d *Decoder) decodeStruct(v reflect.Value, tag string) error {
- panicUnless(v.Kind() == reflect.Struct)
- panicUnless(v.CanSet())
-
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for struct: %q", tag)
- }
-
- for i := 0; i < v.NumField(); i++ {
- fieldInfo := v.Type().Field(i)
- tag := fieldInfo.Tag.Get("rrdbinary")
- if tag == "-" {
- continue
- }
- if err := d.Decode(v.Field(i), tag); err != nil {
- return fmt.Errorf("field %s: %w", fieldInfo.Name, err)
- }
- }
- return nil
-}
-
-func (d *Decoder) decodeList(v reflect.Value, tag string) error {
- panicUnless(v.Kind() == reflect.Array || v.Kind() == reflect.Slice)
- panicUnless(v.CanSet())
-
- for i := 0; i < v.Len(); i++ {
- if err := d.Decode(v.Index(i), tag); err != nil {
- return fmt.Errorf("index %d: %w", i, err)
- }
- }
- return nil
-}
-
-func (obj *String) unmarshalRRD(d *Decoder, tag string) error {
- size := 0
- switch {
- case tag == "":
- // do nothing
- case strings.HasPrefix(tag, "size="):
- var err error
- size, err = strconv.Atoi(strings.TrimPrefix(tag, "size="))
- if err != nil {
- return typeErrorf("invalid rrdbinary struct tag for string: %q", tag)
- }
- default:
- return typeErrorf("invalid rrdbinary struct tag for string: %q", tag)
- }
-
- data := d.data[d.pos:]
- if size > 0 {
- if len(data) < size {
- return d.binErrorf(size, "unexpected end-of-file in %d-byte string", size)
- }
- data = data[:size]
- }
-
- nul := bytes.IndexByte(data, 0)
- if nul < 0 {
- if size > 0 {
- return d.binErrorf(size, "missing null-terminator on %d-byte string", size)
- } else {
- return d.binErrorf(16, "unexpected end-of-file looking for null-terminator on string")
- }
- }
-
- if size > 0 {
- for _, byte := range data[nul:] {
- if byte != 0 {
- return d.binErrorf(size, "garbage data after null-terminator on fixed %d-byte string", size)
- }
- }
- } else {
- size = nul + 1
- }
-
- *obj = String(data[:nul])
- d.pos += size
- return nil
-}
-
-func (obj *Float) unmarshalRRD(d *Decoder, tag string) error {
- if d.arch.FloatWidth != 8 {
- return archErrorf("rrdbinary does not support FloatWidth=%d; only supports 8", d.arch.FloatWidth)
- }
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for float: %q", tag)
- }
-
- data := d.data[d.pos:]
-
- padding := 0
- if d.pos%d.arch.FloatAlign != 0 {
- padding = d.arch.FloatAlign - (d.pos % d.arch.FloatAlign)
- }
- if len(data) < padding {
- return d.binErrorf(padding+d.arch.FloatWidth, "unexpected end-of-file in %d-byte padding-before-float", padding)
- }
- data = data[padding:]
-
- if len(data) < d.arch.FloatWidth {
- return d.binErrorf(d.arch.FloatWidth, "unexpected end-of-file in %d-byte float", d.arch.FloatWidth)
- }
-
- *obj = Float(math.Float64frombits(d.arch.ByteOrder.Uint64(data)))
- d.pos += padding + d.arch.FloatWidth
- return nil
-}
-
-func (obj *Uint) unmarshalRRD(d *Decoder, tag string) error {
- if d.arch.IntWidth != 4 && d.arch.IntWidth != 8 {
- return archErrorf("rrdbinary does not support IntWidth=%d; only supports 4 or 8", d.arch.IntWidth)
- }
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for uint: %q", tag)
- }
-
- data := d.data[d.pos:]
-
- padding := 0
- if d.pos%d.arch.IntAlign != 0 {
- padding = d.arch.IntAlign - (d.pos % d.arch.IntAlign)
- }
- if len(data) < padding {
- return d.binErrorf(padding+d.arch.IntWidth, "unexpected end-of-file in %d-byte padding-before-uint", padding)
- }
- data = data[padding:]
-
- if len(data) < d.arch.IntWidth {
- return d.binErrorf(d.arch.IntWidth, "unexpected end-of-file in %d-byte uint", d.arch.IntWidth)
- }
-
- switch d.arch.IntWidth {
- case 4:
- *obj = Uint(d.arch.ByteOrder.Uint32(data))
- case 8:
- *obj = Uint(d.arch.ByteOrder.Uint64(data))
- }
- d.pos += padding + d.arch.IntWidth
- return nil
-}
-
-func (obj *Int) unmarshalRRD(d *Decoder, tag string) error {
- if d.arch.IntWidth != 4 && d.arch.IntWidth != 8 {
- return archErrorf("rrdbinary does not support IntWidth=%d; only supports 4 or 8", d.arch.IntWidth)
- }
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for int: %q", tag)
- }
-
- data := d.data[d.pos:]
-
- padding := 0
- if d.pos%d.arch.IntAlign != 0 {
- padding = d.arch.IntAlign - (d.pos % d.arch.IntAlign)
- }
- if len(data) < padding {
- return d.binErrorf(padding+d.arch.IntWidth, "unexpected end-of-file in %d-byte padding-before-int", padding)
- }
- data = data[padding:]
-
- if len(data) < d.arch.IntWidth {
- return d.binErrorf(d.arch.IntWidth, "unexpected end-of-file in %d-byte int", d.arch.IntWidth)
- }
-
- switch d.arch.IntWidth {
- case 4:
- *obj = Int(int32(d.arch.ByteOrder.Uint32(data)))
- case 8:
- *obj = Int(d.arch.ByteOrder.Uint64(data))
- }
- d.pos += padding + d.arch.IntWidth
- return nil
-}
-
-func (obj *Unival) unmarshalRRD(d *Decoder, tag string) error {
- if d.arch.UnivalWidth != 8 {
- return archErrorf("rrdbinary does not support UnivalWidth=%d; only supports 8", d.arch.UnivalWidth)
- }
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for unival: %q", tag)
- }
-
- data := d.data[d.pos:]
-
- padding := 0
- if d.pos%d.arch.UnivalAlign != 0 {
- padding = d.arch.UnivalAlign - (d.pos % d.arch.UnivalAlign)
- }
- if len(data) < padding {
- return d.binErrorf(padding+d.arch.UnivalWidth, "unexpected end-of-file in %d-byte padding-before-unival", padding)
- }
- data = data[padding:]
-
- if len(data) < d.arch.UnivalWidth {
- return d.binErrorf(d.arch.UnivalWidth, "unexpected end-of-file in %d-byte unival", d.arch.UnivalWidth)
- }
-
- *obj = Unival(d.arch.ByteOrder.Uint64(data))
- d.pos += padding + d.arch.UnivalWidth
- return nil
-}
-
-func (obj *Time) unmarshalRRD(d *Decoder, tag string) error {
- if d.arch.TimeWidth != 4 && d.arch.TimeWidth != 8 {
- return archErrorf("rrdbinary does not support TimeWidth=%d; only supports 4 or 8", d.arch.TimeWidth)
- }
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for time: %q", tag)
- }
-
- data := d.data[d.pos:]
-
- padding := 0
- if d.pos%d.arch.TimeAlign != 0 {
- padding = d.arch.TimeAlign - (d.pos % d.arch.TimeAlign)
- }
- if len(data) < padding {
- return d.binErrorf(padding+d.arch.TimeWidth, "unexpected end-of-file in %d-byte padding-before-time", padding)
- }
- data = data[padding:]
-
- if len(data) < d.arch.TimeWidth {
- return d.binErrorf(d.arch.TimeWidth, "unexpected end-of-file in %d-byte time", d.arch.TimeWidth)
- }
-
- switch d.arch.TimeWidth {
- case 4:
- *obj = Time(int32(d.arch.ByteOrder.Uint32(data)))
- case 8:
- *obj = Time(d.arch.ByteOrder.Uint64(data))
- }
- d.pos += padding + d.arch.TimeWidth
- return nil
-}
-
-func (_ *EOF) unmarshalRRD(d *Decoder, tag string) error {
- if tag != "" {
- return typeErrorf("invalid rrdbinary struct tag for eof: %q", tag)
- }
-
- data := d.data[d.pos:]
- if len(data) > 0 {
- return d.binErrorf(16, "extra %d bytes of data after expected end-of-file", len(data))
- }
-
- return nil
-}