github.com/lheiskan/zebrapack@v4.1.1-0.20181107023619-e955d028f9bf+incompatible/msgp/json.go (about) 1 package msgp 2 3 import ( 4 "bufio" 5 "encoding/base64" 6 "encoding/json" 7 "io" 8 "strconv" 9 "unicode/utf8" 10 ) 11 12 var ( 13 null = []byte("null") 14 hex = []byte("0123456789abcdef") 15 ) 16 17 var defuns [_maxtype]func(jsWriter, *Reader) (int, error) 18 19 // note: there is an initialization loop if 20 // this isn't set up during init() 21 func init() { 22 // since none of these functions are inline-able, 23 // there is not much of a penalty to the indirect 24 // call. however, this is best expressed as a jump-table... 25 defuns = [_maxtype]func(jsWriter, *Reader) (int, error){ 26 StrType: rwString, 27 BinType: rwBytes, 28 MapType: rwMap, 29 ArrayType: rwArray, 30 Float64Type: rwFloat64, 31 Float32Type: rwFloat32, 32 BoolType: rwBool, 33 IntType: rwInt, 34 UintType: rwUint, 35 NilType: rwNil, 36 ExtensionType: rwExtension, 37 Complex64Type: rwExtension, 38 Complex128Type: rwExtension, 39 TimeType: rwTime, 40 } 41 } 42 43 // this is the interface 44 // used to write json 45 type jsWriter interface { 46 io.Writer 47 io.ByteWriter 48 WriteString(string) (int, error) 49 } 50 51 // CopyToJSON reads MessagePack from 'src' and copies it 52 // as JSON to 'dst' until EOF. 53 func CopyToJSON(dst io.Writer, src io.Reader) (n int64, err error) { 54 r := NewReader(src) 55 n, err = r.WriteToJSON(dst) 56 freeR(r) 57 return 58 } 59 60 // WriteToJSON translates MessagePack from 'r' and writes it as 61 // JSON to 'w' until the underlying reader returns io.EOF. It returns 62 // the number of bytes written, and an error if it stopped before EOF. 63 func (r *Reader) WriteToJSON(w io.Writer) (n int64, err error) { 64 var j jsWriter 65 var bf *bufio.Writer 66 if jsw, ok := w.(jsWriter); ok { 67 j = jsw 68 } else { 69 bf = bufio.NewWriter(w) 70 j = bf 71 } 72 var nn int 73 for err == nil { 74 nn, err = rwNext(j, r) 75 n += int64(nn) 76 } 77 if err != io.EOF { 78 if bf != nil { 79 bf.Flush() 80 } 81 return 82 } 83 err = nil 84 if bf != nil { 85 err = bf.Flush() 86 } 87 return 88 } 89 90 func rwNext(w jsWriter, src *Reader) (int, error) { 91 t, err := src.NextType() 92 if err != nil { 93 return 0, err 94 } 95 return defuns[t](w, src) 96 } 97 98 func rwMap(dst jsWriter, src *Reader) (n int, err error) { 99 var comma bool 100 var sz uint32 101 var field []byte 102 103 sz, err = src.ReadMapHeader() 104 if err != nil { 105 return 106 } 107 108 if sz == 0 { 109 return dst.WriteString("{}") 110 } 111 112 err = dst.WriteByte('{') 113 if err != nil { 114 return 115 } 116 n++ 117 var nn int 118 for i := uint32(0); i < sz; i++ { 119 if comma { 120 err = dst.WriteByte(',') 121 if err != nil { 122 return 123 } 124 n++ 125 } 126 127 field, err = src.ReadMapKeyPtr() 128 if err != nil { 129 return 130 } 131 nn, err = rwquoted(dst, field) 132 n += nn 133 if err != nil { 134 return 135 } 136 137 err = dst.WriteByte(':') 138 if err != nil { 139 return 140 } 141 n++ 142 nn, err = rwNext(dst, src) 143 n += nn 144 if err != nil { 145 return 146 } 147 if !comma { 148 comma = true 149 } 150 } 151 152 err = dst.WriteByte('}') 153 if err != nil { 154 return 155 } 156 n++ 157 return 158 } 159 160 func rwArray(dst jsWriter, src *Reader) (n int, err error) { 161 err = dst.WriteByte('[') 162 if err != nil { 163 return 164 } 165 var sz uint32 166 var nn int 167 sz, err = src.ReadArrayHeader() 168 if err != nil { 169 return 170 } 171 comma := false 172 for i := uint32(0); i < sz; i++ { 173 if comma { 174 err = dst.WriteByte(',') 175 if err != nil { 176 return 177 } 178 n++ 179 } 180 nn, err = rwNext(dst, src) 181 n += nn 182 if err != nil { 183 return 184 } 185 comma = true 186 } 187 188 err = dst.WriteByte(']') 189 if err != nil { 190 return 191 } 192 n++ 193 return 194 } 195 196 func rwNil(dst jsWriter, src *Reader) (int, error) { 197 err := src.ReadNil() 198 if err != nil { 199 return 0, err 200 } 201 return dst.Write(null) 202 } 203 204 func rwFloat32(dst jsWriter, src *Reader) (int, error) { 205 f, err := src.ReadFloat32() 206 if err != nil { 207 return 0, err 208 } 209 src.scratch = strconv.AppendFloat(src.scratch[:0], float64(f), 'f', -1, 64) 210 return dst.Write(src.scratch) 211 } 212 213 func rwFloat64(dst jsWriter, src *Reader) (int, error) { 214 f, err := src.ReadFloat64() 215 if err != nil { 216 return 0, err 217 } 218 src.scratch = strconv.AppendFloat(src.scratch[:0], f, 'f', -1, 32) 219 return dst.Write(src.scratch) 220 } 221 222 func rwInt(dst jsWriter, src *Reader) (int, error) { 223 i, err := src.ReadInt64() 224 if err != nil { 225 return 0, err 226 } 227 src.scratch = strconv.AppendInt(src.scratch[:0], i, 10) 228 return dst.Write(src.scratch) 229 } 230 231 func rwUint(dst jsWriter, src *Reader) (int, error) { 232 u, err := src.ReadUint64() 233 if err != nil { 234 return 0, err 235 } 236 src.scratch = strconv.AppendUint(src.scratch[:0], u, 10) 237 return dst.Write(src.scratch) 238 } 239 240 func rwBool(dst jsWriter, src *Reader) (int, error) { 241 b, err := src.ReadBool() 242 if err != nil { 243 return 0, err 244 } 245 if b { 246 return dst.WriteString("true") 247 } 248 return dst.WriteString("false") 249 } 250 251 func rwTime(dst jsWriter, src *Reader) (int, error) { 252 t, err := src.ReadTime() 253 if err != nil { 254 return 0, err 255 } 256 bts, err := t.MarshalJSON() 257 if err != nil { 258 return 0, err 259 } 260 return dst.Write(bts) 261 } 262 263 func rwExtension(dst jsWriter, src *Reader) (n int, err error) { 264 et, err := src.peekExtensionType() 265 if err != nil { 266 return 0, err 267 } 268 269 // registered extensions can override 270 // the JSON encoding 271 if j, ok := extensionReg[et]; ok { 272 var bts []byte 273 e := j() 274 err = src.ReadExtension(e) 275 if err != nil { 276 return 277 } 278 bts, err = json.Marshal(e) 279 if err != nil { 280 return 281 } 282 return dst.Write(bts) 283 } 284 285 e := RawExtension{} 286 e.Type = et 287 err = src.ReadExtension(&e) 288 if err != nil { 289 return 290 } 291 292 var nn int 293 err = dst.WriteByte('{') 294 if err != nil { 295 return 296 } 297 n++ 298 299 nn, err = dst.WriteString(`"type:"`) 300 n += nn 301 if err != nil { 302 return 303 } 304 305 src.scratch = strconv.AppendInt(src.scratch[0:0], int64(e.Type), 10) 306 nn, err = dst.Write(src.scratch) 307 n += nn 308 if err != nil { 309 return 310 } 311 312 nn, err = dst.WriteString(`,"data":"`) 313 n += nn 314 if err != nil { 315 return 316 } 317 318 enc := base64.NewEncoder(base64.StdEncoding, dst) 319 320 nn, err = enc.Write(e.Data) 321 n += nn 322 if err != nil { 323 return 324 } 325 err = enc.Close() 326 if err != nil { 327 return 328 } 329 nn, err = dst.WriteString(`"}`) 330 n += nn 331 return 332 } 333 334 func rwString(dst jsWriter, src *Reader) (n int, err error) { 335 var p []byte 336 p, err = src.R.Peek(1) 337 if err != nil { 338 return 339 } 340 lead := p[0] 341 var read int 342 343 if isfixstr(lead) { 344 read = int(rfixstr(lead)) 345 src.R.Skip(1) 346 goto write 347 } 348 349 switch lead { 350 case mstr8: 351 p, err = src.R.Next(2) 352 if err != nil { 353 return 354 } 355 read = int(uint8(p[1])) 356 case mstr16: 357 p, err = src.R.Next(3) 358 if err != nil { 359 return 360 } 361 read = int(big.Uint16(p[1:])) 362 case mstr32: 363 p, err = src.R.Next(5) 364 if err != nil { 365 return 366 } 367 read = int(big.Uint32(p[1:])) 368 default: 369 err = badPrefix(StrType, lead) 370 return 371 } 372 write: 373 p, err = src.R.Next(read) 374 if err != nil { 375 return 376 } 377 n, err = rwquoted(dst, p) 378 return 379 } 380 381 func rwBytes(dst jsWriter, src *Reader) (n int, err error) { 382 var nn int 383 err = dst.WriteByte('"') 384 if err != nil { 385 return 386 } 387 n++ 388 src.scratch, err = src.ReadBytes(src.scratch[:0]) 389 if err != nil { 390 return 391 } 392 enc := base64.NewEncoder(base64.StdEncoding, dst) 393 nn, err = enc.Write(src.scratch) 394 n += nn 395 if err != nil { 396 return 397 } 398 err = enc.Close() 399 if err != nil { 400 return 401 } 402 err = dst.WriteByte('"') 403 if err != nil { 404 return 405 } 406 n++ 407 return 408 } 409 410 // Below (c) The Go Authors, 2009-2014 411 // Subject to the BSD-style license found at http://golang.org 412 // 413 // see: encoding/json/encode.go:(*encodeState).stringbytes() 414 func rwquoted(dst jsWriter, s []byte) (n int, err error) { 415 var nn int 416 err = dst.WriteByte('"') 417 if err != nil { 418 return 419 } 420 n++ 421 start := 0 422 for i := 0; i < len(s); { 423 if b := s[i]; b < utf8.RuneSelf { 424 if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { 425 i++ 426 continue 427 } 428 if start < i { 429 nn, err = dst.Write(s[start:i]) 430 n += nn 431 if err != nil { 432 return 433 } 434 } 435 switch b { 436 case '\\', '"': 437 err = dst.WriteByte('\\') 438 if err != nil { 439 return 440 } 441 n++ 442 err = dst.WriteByte(b) 443 if err != nil { 444 return 445 } 446 n++ 447 case '\n': 448 err = dst.WriteByte('\\') 449 if err != nil { 450 return 451 } 452 n++ 453 err = dst.WriteByte('n') 454 if err != nil { 455 return 456 } 457 n++ 458 case '\r': 459 err = dst.WriteByte('\\') 460 if err != nil { 461 return 462 } 463 n++ 464 err = dst.WriteByte('r') 465 if err != nil { 466 return 467 } 468 n++ 469 default: 470 nn, err = dst.WriteString(`\u00`) 471 n += nn 472 if err != nil { 473 return 474 } 475 err = dst.WriteByte(hex[b>>4]) 476 if err != nil { 477 return 478 } 479 n++ 480 err = dst.WriteByte(hex[b&0xF]) 481 if err != nil { 482 return 483 } 484 n++ 485 } 486 i++ 487 start = i 488 continue 489 } 490 c, size := utf8.DecodeRune(s[i:]) 491 if c == utf8.RuneError && size == 1 { 492 if start < i { 493 nn, err = dst.Write(s[start:i]) 494 n += nn 495 if err != nil { 496 return 497 } 498 nn, err = dst.WriteString(`\ufffd`) 499 n += nn 500 if err != nil { 501 return 502 } 503 i += size 504 start = i 505 continue 506 } 507 } 508 if c == '\u2028' || c == '\u2029' { 509 if start < i { 510 nn, err = dst.Write(s[start:i]) 511 n += nn 512 if err != nil { 513 return 514 } 515 nn, err = dst.WriteString(`\u202`) 516 n += nn 517 if err != nil { 518 return 519 } 520 err = dst.WriteByte(hex[c&0xF]) 521 if err != nil { 522 return 523 } 524 n++ 525 } 526 } 527 i += size 528 } 529 if start < len(s) { 530 nn, err = dst.Write(s[start:]) 531 n += nn 532 if err != nil { 533 return 534 } 535 } 536 err = dst.WriteByte('"') 537 if err != nil { 538 return 539 } 540 n++ 541 return 542 }