github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/msgp/number.go (about) 1 package msgp 2 3 import ( 4 "math" 5 "strconv" 6 ) 7 8 // The portable parts of the Number implementation 9 10 // Number can be 11 // an int64, uint64, float32, 12 // or float64 internally. 13 // It can decode itself 14 // from any of the native 15 // messagepack number types. 16 // The zero-value of Number 17 // is Int(0). Using the equality 18 // operator with Number compares 19 // both the type and the value 20 // of the number. 21 type Number struct { 22 // internally, this 23 // is just a tagged union. 24 // the raw bits of the number 25 // are stored the same way regardless. 26 bits uint64 27 typ Type 28 } 29 30 // AsInt sets the number to an int64. 31 func (n *Number) AsInt(i int64) { 32 33 // we always store int(0) 34 // as {0, InvalidType} in 35 // order to preserve 36 // the behavior of the == operator 37 if i == 0 { 38 n.typ = InvalidType 39 n.bits = 0 40 return 41 } 42 43 n.typ = IntType 44 n.bits = uint64(i) 45 } 46 47 // AsUint sets the number to a uint64. 48 func (n *Number) AsUint(u uint64) { 49 n.typ = UintType 50 n.bits = u 51 } 52 53 // AsFloat32 sets the value of the number 54 // to a float32. 55 func (n *Number) AsFloat32(f float32) { 56 n.typ = Float32Type 57 n.bits = uint64(math.Float32bits(f)) 58 } 59 60 // AsFloat64 sets the value of the 61 // number to a float64. 62 func (n *Number) AsFloat64(f float64) { 63 n.typ = Float64Type 64 n.bits = math.Float64bits(f) 65 } 66 67 // Int casts the number as an int64, and 68 // returns whether or not that was the 69 // underlying type. 70 func (n *Number) Int() (int64, bool) { 71 return int64(n.bits), n.typ == IntType || n.typ == InvalidType 72 } 73 74 // Uint casts the number as a uint64, and returns 75 // whether or not that was the underlying type. 76 func (n *Number) Uint() (uint64, bool) { 77 return n.bits, n.typ == UintType 78 } 79 80 // Float casts the number to a float64, and 81 // returns whether or not that was the underlying 82 // type (either a float64 or a float32). 83 func (n *Number) Float() (float64, bool) { 84 switch n.typ { 85 case Float32Type: 86 return float64(math.Float32frombits(uint32(n.bits))), true 87 case Float64Type: 88 return math.Float64frombits(n.bits), true 89 default: 90 return 0.0, false 91 } 92 } 93 94 // Type will return one of: 95 // Float64Type, Float32Type, UintType, or IntType. 96 func (n *Number) Type() Type { 97 if n.typ == InvalidType { 98 return IntType 99 } 100 return n.typ 101 } 102 103 // DecodeMsg implements msgp.Decodable 104 func (n *Number) DecodeMsg(r *Reader) error { 105 typ, err := r.NextType() 106 if err != nil { 107 return err 108 } 109 switch typ { 110 case Float32Type: 111 f, err := r.ReadFloat32() 112 if err != nil { 113 return err 114 } 115 n.AsFloat32(f) 116 return nil 117 case Float64Type: 118 f, err := r.ReadFloat64() 119 if err != nil { 120 return err 121 } 122 n.AsFloat64(f) 123 return nil 124 case IntType: 125 i, err := r.ReadInt64() 126 if err != nil { 127 return err 128 } 129 n.AsInt(i) 130 return nil 131 case UintType: 132 u, err := r.ReadUint64() 133 if err != nil { 134 return err 135 } 136 n.AsUint(u) 137 return nil 138 default: 139 return TypeError{Encoded: typ, Method: IntType} 140 } 141 } 142 143 // UnmarshalMsg implements msgp.Unmarshaler 144 func (n *Number) UnmarshalMsg(b []byte) ([]byte, error) { 145 var nbs *NilBitsStack 146 typ := NextType(b) 147 switch typ { 148 case IntType: 149 i, o, err := nbs.ReadInt64Bytes(b) 150 if err != nil { 151 return b, err 152 } 153 n.AsInt(i) 154 return o, nil 155 case UintType: 156 u, o, err := nbs.ReadUint64Bytes(b) 157 if err != nil { 158 return b, err 159 } 160 n.AsUint(u) 161 return o, nil 162 case Float64Type: 163 f, o, err := nbs.ReadFloat64Bytes(b) 164 if err != nil { 165 return b, err 166 } 167 n.AsFloat64(f) 168 return o, nil 169 case Float32Type: 170 f, o, err := nbs.ReadFloat32Bytes(b) 171 if err != nil { 172 return b, err 173 } 174 n.AsFloat32(f) 175 return o, nil 176 default: 177 return b, TypeError{Method: IntType, Encoded: typ} 178 } 179 } 180 181 // MarshalMsg implements msgp.Marshaler 182 func (n *Number) MarshalMsg(b []byte) ([]byte, error) { 183 switch n.typ { 184 case IntType: 185 return AppendInt64(b, int64(n.bits)), nil 186 case UintType: 187 return AppendUint64(b, uint64(n.bits)), nil 188 case Float64Type: 189 return AppendFloat64(b, math.Float64frombits(n.bits)), nil 190 case Float32Type: 191 return AppendFloat32(b, math.Float32frombits(uint32(n.bits))), nil 192 default: 193 return AppendInt64(b, 0), nil 194 } 195 } 196 197 // EncodeMsg implements msgp.Encodable 198 func (n *Number) EncodeMsg(w *Writer) error { 199 switch n.typ { 200 case IntType: 201 return w.WriteInt64(int64(n.bits)) 202 case UintType: 203 return w.WriteUint64(n.bits) 204 case Float64Type: 205 return w.WriteFloat64(math.Float64frombits(n.bits)) 206 case Float32Type: 207 return w.WriteFloat32(math.Float32frombits(uint32(n.bits))) 208 default: 209 return w.WriteInt64(0) 210 } 211 } 212 213 // Msgsize implements msgp.Sizer 214 func (n *Number) Msgsize() int { 215 switch n.typ { 216 case Float32Type: 217 return Float32Size 218 case Float64Type: 219 return Float64Size 220 case IntType: 221 return Int64Size 222 case UintType: 223 return Uint64Size 224 default: 225 return 1 // fixint(0) 226 } 227 } 228 229 // MarshalJSON implements json.Marshaler 230 func (n *Number) MarshalJSON() ([]byte, error) { 231 t := n.Type() 232 if t == InvalidType { 233 return []byte{'0'}, nil 234 } 235 out := make([]byte, 0, 32) 236 switch t { 237 case Float32Type, Float64Type: 238 f, _ := n.Float() 239 return strconv.AppendFloat(out, f, 'f', -1, 64), nil 240 case IntType: 241 i, _ := n.Int() 242 return strconv.AppendInt(out, i, 10), nil 243 case UintType: 244 u, _ := n.Uint() 245 return strconv.AppendUint(out, u, 10), nil 246 default: 247 panic("(*Number).typ is invalid") 248 } 249 } 250 251 // String implements fmt.Stringer 252 func (n *Number) String() string { 253 switch n.typ { 254 case InvalidType: 255 return "0" 256 case Float32Type, Float64Type: 257 f, _ := n.Float() 258 return strconv.FormatFloat(f, 'f', -1, 64) 259 case IntType: 260 i, _ := n.Int() 261 return strconv.FormatInt(i, 10) 262 case UintType: 263 u, _ := n.Uint() 264 return strconv.FormatUint(u, 10) 265 default: 266 panic("(*Number).typ is invalid") 267 } 268 }