github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/msgp/json_bytes.go (about) 1 package msgp 2 3 import ( 4 "bufio" 5 "encoding/base64" 6 "encoding/json" 7 "io" 8 "strconv" 9 "time" 10 ) 11 12 var unfuns [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error) 13 14 func init() { 15 16 // NOTE(pmh): this is best expressed as a jump table, 17 // but gc doesn't do that yet. revisit post-go1.5. 18 unfuns = [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error){ 19 StrType: rwStringBytes, 20 BinType: rwBytesBytes, 21 MapType: rwMapBytes, 22 ArrayType: rwArrayBytes, 23 Float64Type: rwFloat64Bytes, 24 Float32Type: rwFloat32Bytes, 25 BoolType: rwBoolBytes, 26 IntType: rwIntBytes, 27 UintType: rwUintBytes, 28 NilType: rwNullBytes, 29 ExtensionType: rwExtensionBytes, 30 Complex64Type: rwExtensionBytes, 31 Complex128Type: rwExtensionBytes, 32 TimeType: rwTimeBytes, 33 } 34 } 35 36 // UnmarshalAsJSON takes raw messagepack and writes 37 // it as JSON to 'w'. If an error is returned, the 38 // bytes not translated will also be returned. If 39 // no errors are encountered, the length of the returned 40 // slice will be zero. 41 func UnmarshalAsJSON(w io.Writer, msg []byte) ([]byte, error) { 42 var ( 43 scratch []byte 44 cast bool 45 dst jsWriter 46 err error 47 ) 48 if jsw, ok := w.(jsWriter); ok { 49 dst = jsw 50 cast = true 51 } else { 52 dst = bufio.NewWriterSize(w, 512) 53 } 54 for len(msg) > 0 && err == nil { 55 msg, scratch, err = writeNext(dst, msg, scratch) 56 } 57 if !cast && err == nil { 58 err = dst.(*bufio.Writer).Flush() 59 } 60 return msg, err 61 } 62 63 func writeNext(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 64 if len(msg) < 1 { 65 return msg, scratch, ErrShortBytes 66 } 67 t := getType(msg[0]) 68 if t == InvalidType { 69 return msg, scratch, InvalidPrefixError(msg[0]) 70 } 71 if t == ExtensionType { 72 et, err := peekExtension(msg) 73 if err != nil { 74 return nil, scratch, err 75 } 76 if et == TimeExtension { 77 t = TimeType 78 } 79 } 80 return unfuns[t](w, msg, scratch) 81 } 82 83 func rwArrayBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 84 var nbs *NilBitsStack 85 sz, msg, err := nbs.ReadArrayHeaderBytes(msg) 86 if err != nil { 87 return msg, scratch, err 88 } 89 err = w.WriteByte('[') 90 if err != nil { 91 return msg, scratch, err 92 } 93 for i := uint32(0); i < sz; i++ { 94 if i != 0 { 95 err = w.WriteByte(',') 96 if err != nil { 97 return msg, scratch, err 98 } 99 } 100 msg, scratch, err = writeNext(w, msg, scratch) 101 if err != nil { 102 return msg, scratch, err 103 } 104 } 105 err = w.WriteByte(']') 106 return msg, scratch, err 107 } 108 109 func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 110 var nbs *NilBitsStack 111 sz, msg, err := nbs.ReadMapHeaderBytes(msg) 112 if err != nil { 113 return msg, scratch, err 114 } 115 err = w.WriteByte('{') 116 if err != nil { 117 return msg, scratch, err 118 } 119 for i := uint32(0); i < sz; i++ { 120 if i != 0 { 121 err = w.WriteByte(',') 122 if err != nil { 123 return msg, scratch, err 124 } 125 } 126 msg, scratch, err = rwMapKeyBytes(w, msg, scratch) 127 if err != nil { 128 return msg, scratch, err 129 } 130 err = w.WriteByte(':') 131 if err != nil { 132 return msg, scratch, err 133 } 134 msg, scratch, err = writeNext(w, msg, scratch) 135 if err != nil { 136 return msg, scratch, err 137 } 138 } 139 err = w.WriteByte('}') 140 return msg, scratch, err 141 } 142 143 func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 144 msg, scratch, err := rwStringBytes(w, msg, scratch) 145 if err != nil { 146 if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType { 147 return rwBytesBytes(w, msg, scratch) 148 } 149 } 150 return msg, scratch, err 151 } 152 153 func rwStringBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 154 var nbs *NilBitsStack 155 str, msg, err := nbs.ReadStringZC(msg) 156 if err != nil { 157 return msg, scratch, err 158 } 159 _, err = rwquoted(w, str) 160 return msg, scratch, err 161 } 162 163 func rwBytesBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 164 var nbs *NilBitsStack 165 bts, msg, err := nbs.ReadBytesZC(msg) 166 if err != nil { 167 return msg, scratch, err 168 } 169 l := base64.StdEncoding.EncodedLen(len(bts)) 170 if cap(scratch) >= l { 171 scratch = scratch[0:l] 172 } else { 173 scratch = make([]byte, l) 174 } 175 base64.StdEncoding.Encode(scratch, bts) 176 err = w.WriteByte('"') 177 if err != nil { 178 return msg, scratch, err 179 } 180 _, err = w.Write(scratch) 181 if err != nil { 182 return msg, scratch, err 183 } 184 err = w.WriteByte('"') 185 return msg, scratch, err 186 } 187 188 func rwNullBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 189 var nbs *NilBitsStack 190 msg, err := nbs.ReadNilBytes(msg) 191 if err != nil { 192 return msg, scratch, err 193 } 194 _, err = w.Write(null) 195 return msg, scratch, err 196 } 197 198 func rwBoolBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 199 var nbs *NilBitsStack 200 b, msg, err := nbs.ReadBoolBytes(msg) 201 if err != nil { 202 return msg, scratch, err 203 } 204 if b { 205 _, err = w.WriteString("true") 206 return msg, scratch, err 207 } 208 _, err = w.WriteString("false") 209 return msg, scratch, err 210 } 211 212 func rwIntBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 213 var nbs *NilBitsStack 214 i, msg, err := nbs.ReadInt64Bytes(msg) 215 if err != nil { 216 return msg, scratch, err 217 } 218 scratch = strconv.AppendInt(scratch[0:0], i, 10) 219 _, err = w.Write(scratch) 220 return msg, scratch, err 221 } 222 223 func rwUintBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 224 var nbs *NilBitsStack 225 u, msg, err := nbs.ReadUint64Bytes(msg) 226 if err != nil { 227 return msg, scratch, err 228 } 229 scratch = strconv.AppendUint(scratch[0:0], u, 10) 230 _, err = w.Write(scratch) 231 return msg, scratch, err 232 } 233 234 func rwFloatBytes(w jsWriter, msg []byte, f64 bool, scratch []byte) ([]byte, []byte, error) { 235 var nbs *NilBitsStack 236 var f float64 237 var err error 238 var sz int 239 if f64 { 240 sz = 64 241 f, msg, err = nbs.ReadFloat64Bytes(msg) 242 } else { 243 sz = 32 244 var v float32 245 v, msg, err = nbs.ReadFloat32Bytes(msg) 246 f = float64(v) 247 } 248 if err != nil { 249 return msg, scratch, err 250 } 251 scratch = strconv.AppendFloat(scratch, f, 'f', -1, sz) 252 _, err = w.Write(scratch) 253 return msg, scratch, err 254 } 255 256 func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 257 var nbs *NilBitsStack 258 var f float32 259 var err error 260 f, msg, err = nbs.ReadFloat32Bytes(msg) 261 if err != nil { 262 return msg, scratch, err 263 } 264 scratch = strconv.AppendFloat(scratch[:0], float64(f), 'f', -1, 32) 265 _, err = w.Write(scratch) 266 return msg, scratch, err 267 } 268 269 func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 270 var nbs *NilBitsStack 271 var f float64 272 var err error 273 f, msg, err = nbs.ReadFloat64Bytes(msg) 274 if err != nil { 275 return msg, scratch, err 276 } 277 scratch = strconv.AppendFloat(scratch[:0], f, 'f', -1, 64) 278 _, err = w.Write(scratch) 279 return msg, scratch, err 280 } 281 282 func rwTimeBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 283 var nbs *NilBitsStack 284 var t time.Time 285 var err error 286 t, msg, err = nbs.ReadTimeBytes(msg) 287 if err != nil { 288 return msg, scratch, err 289 } 290 bts, err := t.MarshalJSON() 291 if err != nil { 292 return msg, scratch, err 293 } 294 _, err = w.Write(bts) 295 return msg, scratch, err 296 } 297 298 func rwExtensionBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { 299 var nbs *NilBitsStack 300 var err error 301 var et int8 302 et, err = peekExtension(msg) 303 if err != nil { 304 return msg, scratch, err 305 } 306 307 // if it's time.Time 308 if et == TimeExtension { 309 var tm time.Time 310 tm, msg, err = nbs.ReadTimeBytes(msg) 311 if err != nil { 312 return msg, scratch, err 313 } 314 bts, err := tm.MarshalJSON() 315 if err != nil { 316 return msg, scratch, err 317 } 318 _, err = w.Write(bts) 319 return msg, scratch, err 320 } 321 322 // if the extension is registered, 323 // use its canonical JSON form 324 if f, ok := extensionReg[et]; ok { 325 e := f() 326 msg, err = nbs.ReadExtensionBytes(msg, e) 327 if err != nil { 328 return msg, scratch, err 329 } 330 bts, err := json.Marshal(e) 331 if err != nil { 332 return msg, scratch, err 333 } 334 _, err = w.Write(bts) 335 return msg, scratch, err 336 } 337 338 // otherwise, write `{"type": <num>, "data": "<base64data>"}` 339 r := RawExtension{} 340 r.Type = et 341 msg, err = nbs.ReadExtensionBytes(msg, &r) 342 if err != nil { 343 return msg, scratch, err 344 } 345 scratch, err = writeExt(w, r, scratch) 346 return msg, scratch, err 347 } 348 349 func writeExt(w jsWriter, r RawExtension, scratch []byte) ([]byte, error) { 350 _, err := w.WriteString(`{"type":`) 351 if err != nil { 352 return scratch, err 353 } 354 scratch = strconv.AppendInt(scratch[0:0], int64(r.Type), 10) 355 _, err = w.Write(scratch) 356 if err != nil { 357 return scratch, err 358 } 359 _, err = w.WriteString(`,"data":"`) 360 if err != nil { 361 return scratch, err 362 } 363 l := base64.StdEncoding.EncodedLen(len(r.Data)) 364 if cap(scratch) >= l { 365 scratch = scratch[0:l] 366 } else { 367 scratch = make([]byte, l) 368 } 369 base64.StdEncoding.Encode(scratch, r.Data) 370 _, err = w.Write(scratch) 371 if err != nil { 372 return scratch, err 373 } 374 _, err = w.WriteString(`"}`) 375 return scratch, err 376 }