]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/vmihailenco/msgpack/time.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / vmihailenco / msgpack / time.go
1 package msgpack
2
3 import (
4 "encoding/binary"
5 "fmt"
6 "reflect"
7 "time"
8
9 "github.com/vmihailenco/msgpack/codes"
10 )
11
12 var timeExtId int8 = -1
13
14 func init() {
15 timeType := reflect.TypeOf((*time.Time)(nil)).Elem()
16 registerExt(timeExtId, timeType, encodeTimeValue, decodeTimeValue)
17 }
18
19 func (e *Encoder) EncodeTime(tm time.Time) error {
20 b := e.encodeTime(tm)
21 if err := e.encodeExtLen(len(b)); err != nil {
22 return err
23 }
24 if err := e.w.WriteByte(byte(timeExtId)); err != nil {
25 return err
26 }
27 return e.write(b)
28 }
29
30 func (e *Encoder) encodeTime(tm time.Time) []byte {
31 secs := uint64(tm.Unix())
32 if secs>>34 == 0 {
33 data := uint64(tm.Nanosecond())<<34 | secs
34 if data&0xffffffff00000000 == 0 {
35 b := make([]byte, 4)
36 binary.BigEndian.PutUint32(b, uint32(data))
37 return b
38 } else {
39 b := make([]byte, 8)
40 binary.BigEndian.PutUint64(b, data)
41 return b
42 }
43 }
44
45 b := make([]byte, 12)
46 binary.BigEndian.PutUint32(b, uint32(tm.Nanosecond()))
47 binary.BigEndian.PutUint64(b[4:], uint64(secs))
48 return b
49 }
50
51 func (d *Decoder) DecodeTime() (time.Time, error) {
52 tm, err := d.decodeTime()
53 if err != nil {
54 return tm, err
55 }
56
57 if tm.IsZero() {
58 // Assume that zero time does not have timezone information.
59 return tm.UTC(), nil
60 }
61 return tm, nil
62 }
63
64 func (d *Decoder) decodeTime() (time.Time, error) {
65 extLen := d.extLen
66 d.extLen = 0
67 if extLen == 0 {
68 c, err := d.readCode()
69 if err != nil {
70 return time.Time{}, err
71 }
72
73 // Legacy format.
74 if c == codes.FixedArrayLow|2 {
75 sec, err := d.DecodeInt64()
76 if err != nil {
77 return time.Time{}, err
78 }
79
80 nsec, err := d.DecodeInt64()
81 if err != nil {
82 return time.Time{}, err
83 }
84
85 return time.Unix(sec, nsec), nil
86 }
87
88 if codes.IsString(c) {
89 s, err := d.string(c)
90 if err != nil {
91 return time.Time{}, err
92 }
93 return time.Parse(time.RFC3339Nano, s)
94 }
95
96 extLen, err = d.parseExtLen(c)
97 if err != nil {
98 return time.Time{}, err
99 }
100
101 // Skip ext id.
102 _, err = d.s.ReadByte()
103 if err != nil {
104 return time.Time{}, nil
105 }
106 }
107
108 b, err := d.readN(extLen)
109 if err != nil {
110 return time.Time{}, err
111 }
112
113 switch len(b) {
114 case 4:
115 sec := binary.BigEndian.Uint32(b)
116 return time.Unix(int64(sec), 0), nil
117 case 8:
118 sec := binary.BigEndian.Uint64(b)
119 nsec := int64(sec >> 34)
120 sec &= 0x00000003ffffffff
121 return time.Unix(int64(sec), nsec), nil
122 case 12:
123 nsec := binary.BigEndian.Uint32(b)
124 sec := binary.BigEndian.Uint64(b[4:])
125 return time.Unix(int64(sec), int64(nsec)), nil
126 default:
127 err = fmt.Errorf("msgpack: invalid ext len=%d decoding time", extLen)
128 return time.Time{}, err
129 }
130 }
131
132 func encodeTimeValue(e *Encoder, v reflect.Value) error {
133 tm := v.Interface().(time.Time)
134 b := e.encodeTime(tm)
135 return e.write(b)
136 }
137
138 func decodeTimeValue(d *Decoder, v reflect.Value) error {
139 tm, err := d.DecodeTime()
140 if err != nil {
141 return err
142 }
143 v.Set(reflect.ValueOf(tm))
144 return nil
145 }