summaryrefslogtreecommitdiff
path: root/rrdformat/rrdbinary/unmarshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'rrdformat/rrdbinary/unmarshal.go')
-rw-r--r--rrdformat/rrdbinary/unmarshal.go87
1 files changed, 78 insertions, 9 deletions
diff --git a/rrdformat/rrdbinary/unmarshal.go b/rrdformat/rrdbinary/unmarshal.go
index be0b492..34fc537 100644
--- a/rrdformat/rrdbinary/unmarshal.go
+++ b/rrdformat/rrdbinary/unmarshal.go
@@ -46,6 +46,8 @@ func (d *unmarshaler) unmarshal(v reflect.Value, tag string) error {
return d.unmarshalUint(v, tag)
case reflect.TypeOf(Unival(0)):
return d.unmarshalUnival(v, tag)
+ case reflect.TypeOf(Timestamp{}):
+ return d.unmarshalTimestamp(v, tag)
default:
switch v.Type().Kind() {
case reflect.Struct:
@@ -176,8 +178,8 @@ func (d *unmarshaler) unmarshalUint(v reflect.Value, tag string) error {
panicUnless(v.Type() == reflect.TypeOf(Uint(0)))
panicUnless(v.CanSet())
- if d.arch.UintWidth != 4 && d.arch.UintWidth != 8 {
- return archErrorf("rrdbinary does not support UintWidth=%d; only supports 4 or 8", d.arch.UintWidth)
+ 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)
@@ -186,25 +188,25 @@ func (d *unmarshaler) unmarshalUint(v reflect.Value, tag string) error {
data := d.data[d.pos:]
padding := 0
- if d.pos%d.arch.UintAlign != 0 {
- padding = d.arch.UintAlign - (d.pos % d.arch.UintAlign)
+ 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.UintWidth, "unexpected end-of-file in %d-byte padding-before-uint", 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.UintWidth {
- return d.binErrorf(d.arch.UintWidth, "unexpected end-of-file in %d-byte uint", d.arch.UintWidth)
+ 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.UintWidth {
+ switch d.arch.IntWidth {
case 4:
v.SetUint(uint64(d.arch.ByteOrder.Uint32(data)))
case 8:
v.SetUint(d.arch.ByteOrder.Uint64(data))
}
- d.pos += padding + d.arch.UintWidth
+ d.pos += padding + d.arch.IntWidth
return nil
}
@@ -238,3 +240,70 @@ func (d *unmarshaler) unmarshalUnival(v reflect.Value, tag string) error {
d.pos += padding + d.arch.UnivalWidth
return nil
}
+
+func (d *unmarshaler) unmarshalTimestamp(v reflect.Value, tag string) error {
+ panicUnless(v.Type() == reflect.TypeOf(Timestamp{}))
+ panicUnless(v.CanSet())
+
+ if tag != "" {
+ return typeErrorf("invalid rrdbinary struct tag for timestamp: %q", tag)
+ }
+
+ data := d.data[d.pos:]
+ var sec, usec int64
+
+ // seconds -- time_t
+ 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)
+ }
+ // padding
+ 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_t", padding)
+ }
+ data = data[padding:]
+ // value
+ if len(data) < d.arch.TimeWidth {
+ return d.binErrorf(d.arch.TimeWidth, "unexpected end-of-file in %d-byte time_t", d.arch.TimeWidth)
+ }
+ switch d.arch.TimeWidth {
+ case 4:
+ sec = int64(d.arch.ByteOrder.Int32(data))
+ case 8:
+ sec = d.arch.ByteOrder.Int64(data)
+ }
+ data = data[d.arch.TimeWidth:]
+
+ // nanoseconds -- long
+ 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)
+ }
+ // padding
+ 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:]
+ // value
+ 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:
+ usec = int64(d.arch.ByteOrder.Int32(data))
+ case 8:
+ usec = d.arch.ByteOrder.Int64(data)
+ }
+ data = data[d.arch.IntWidth:]
+
+ // put it all together
+ v.Set(reflect.ValueOf(time.Unix(sec, usec*1000)))
+ d.pos = len(pos.data) - len(data)
+ return nil
+}