summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/vmihailenco/msgpack/v5/time.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/vmihailenco/msgpack/v5/time.go')
-rw-r--r--vendor/github.com/vmihailenco/msgpack/v5/time.go145
1 files changed, 145 insertions, 0 deletions
diff --git a/vendor/github.com/vmihailenco/msgpack/v5/time.go b/vendor/github.com/vmihailenco/msgpack/v5/time.go
new file mode 100644
index 00000000..44566ec0
--- /dev/null
+++ b/vendor/github.com/vmihailenco/msgpack/v5/time.go
@@ -0,0 +1,145 @@
+package msgpack
+
+import (
+ "encoding/binary"
+ "fmt"
+ "reflect"
+ "time"
+
+ "github.com/vmihailenco/msgpack/v5/msgpcode"
+)
+
+var timeExtID int8 = -1
+
+func init() {
+ RegisterExtEncoder(timeExtID, time.Time{}, timeEncoder)
+ RegisterExtDecoder(timeExtID, time.Time{}, timeDecoder)
+}
+
+func timeEncoder(e *Encoder, v reflect.Value) ([]byte, error) {
+ return e.encodeTime(v.Interface().(time.Time)), nil
+}
+
+func timeDecoder(d *Decoder, v reflect.Value, extLen int) error {
+ tm, err := d.decodeTime(extLen)
+ if err != nil {
+ return err
+ }
+
+ ptr := v.Addr().Interface().(*time.Time)
+ *ptr = tm
+
+ return nil
+}
+
+func (e *Encoder) EncodeTime(tm time.Time) error {
+ b := e.encodeTime(tm)
+ if err := e.encodeExtLen(len(b)); err != nil {
+ return err
+ }
+ if err := e.w.WriteByte(byte(timeExtID)); err != nil {
+ return err
+ }
+ return e.write(b)
+}
+
+func (e *Encoder) encodeTime(tm time.Time) []byte {
+ if e.timeBuf == nil {
+ e.timeBuf = make([]byte, 12)
+ }
+
+ secs := uint64(tm.Unix())
+ if secs>>34 == 0 {
+ data := uint64(tm.Nanosecond())<<34 | secs
+
+ if data&0xffffffff00000000 == 0 {
+ b := e.timeBuf[:4]
+ binary.BigEndian.PutUint32(b, uint32(data))
+ return b
+ }
+
+ b := e.timeBuf[:8]
+ binary.BigEndian.PutUint64(b, data)
+ return b
+ }
+
+ b := e.timeBuf[:12]
+ binary.BigEndian.PutUint32(b, uint32(tm.Nanosecond()))
+ binary.BigEndian.PutUint64(b[4:], secs)
+ return b
+}
+
+func (d *Decoder) DecodeTime() (time.Time, error) {
+ c, err := d.readCode()
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ // Legacy format.
+ if c == msgpcode.FixedArrayLow|2 {
+ sec, err := d.DecodeInt64()
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ nsec, err := d.DecodeInt64()
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ return time.Unix(sec, nsec), nil
+ }
+
+ if msgpcode.IsString(c) {
+ s, err := d.string(c)
+ if err != nil {
+ return time.Time{}, err
+ }
+ return time.Parse(time.RFC3339Nano, s)
+ }
+
+ extID, extLen, err := d.extHeader(c)
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ if extID != timeExtID {
+ return time.Time{}, fmt.Errorf("msgpack: invalid time ext id=%d", extID)
+ }
+
+ tm, err := d.decodeTime(extLen)
+ if err != nil {
+ return tm, err
+ }
+
+ if tm.IsZero() {
+ // Zero time does not have timezone information.
+ return tm.UTC(), nil
+ }
+ return tm, nil
+}
+
+func (d *Decoder) decodeTime(extLen int) (time.Time, error) {
+ b, err := d.readN(extLen)
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ switch len(b) {
+ case 4:
+ sec := binary.BigEndian.Uint32(b)
+ return time.Unix(int64(sec), 0), nil
+ case 8:
+ sec := binary.BigEndian.Uint64(b)
+ nsec := int64(sec >> 34)
+ sec &= 0x00000003ffffffff
+ return time.Unix(int64(sec), nsec), nil
+ case 12:
+ nsec := binary.BigEndian.Uint32(b)
+ sec := binary.BigEndian.Uint64(b[4:])
+ return time.Unix(int64(sec), int64(nsec)), nil
+ default:
+ err = fmt.Errorf("msgpack: invalid ext len=%d decoding time", extLen)
+ return time.Time{}, err
+ }
+}