diff options
Diffstat (limited to 'vendor/github.com/vmihailenco/msgpack/time.go')
-rw-r--r-- | vendor/github.com/vmihailenco/msgpack/time.go | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/vendor/github.com/vmihailenco/msgpack/time.go b/vendor/github.com/vmihailenco/msgpack/time.go new file mode 100644 index 0000000..f740969 --- /dev/null +++ b/vendor/github.com/vmihailenco/msgpack/time.go | |||
@@ -0,0 +1,145 @@ | |||
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 | } | ||