khenaidoo | ac63710 | 2019-01-14 15:44:34 -0500 | [diff] [blame^] | 1 | package cbor |
| 2 | |
| 3 | // This file contains code to decode a stream of CBOR Data into JSON. |
| 4 | |
| 5 | import ( |
| 6 | "bufio" |
| 7 | "bytes" |
| 8 | "fmt" |
| 9 | "io" |
| 10 | "math" |
| 11 | "net" |
| 12 | "runtime" |
| 13 | "strconv" |
| 14 | "strings" |
| 15 | "time" |
| 16 | "unicode/utf8" |
| 17 | ) |
| 18 | |
| 19 | var decodeTimeZone *time.Location |
| 20 | |
| 21 | const hexTable = "0123456789abcdef" |
| 22 | |
| 23 | const isFloat32 = 4 |
| 24 | const isFloat64 = 8 |
| 25 | |
| 26 | func readNBytes(src *bufio.Reader, n int) []byte { |
| 27 | ret := make([]byte, n) |
| 28 | for i := 0; i < n; i++ { |
| 29 | ch, e := src.ReadByte() |
| 30 | if e != nil { |
| 31 | panic(fmt.Errorf("Tried to Read %d Bytes.. But hit end of file", n)) |
| 32 | } |
| 33 | ret[i] = ch |
| 34 | } |
| 35 | return ret |
| 36 | } |
| 37 | |
| 38 | func readByte(src *bufio.Reader) byte { |
| 39 | b, e := src.ReadByte() |
| 40 | if e != nil { |
| 41 | panic(fmt.Errorf("Tried to Read 1 Byte.. But hit end of file")) |
| 42 | } |
| 43 | return b |
| 44 | } |
| 45 | |
| 46 | func decodeIntAdditonalType(src *bufio.Reader, minor byte) int64 { |
| 47 | val := int64(0) |
| 48 | if minor <= 23 { |
| 49 | val = int64(minor) |
| 50 | } else { |
| 51 | bytesToRead := 0 |
| 52 | switch minor { |
| 53 | case additionalTypeIntUint8: |
| 54 | bytesToRead = 1 |
| 55 | case additionalTypeIntUint16: |
| 56 | bytesToRead = 2 |
| 57 | case additionalTypeIntUint32: |
| 58 | bytesToRead = 4 |
| 59 | case additionalTypeIntUint64: |
| 60 | bytesToRead = 8 |
| 61 | default: |
| 62 | panic(fmt.Errorf("Invalid Additional Type: %d in decodeInteger (expected <28)", minor)) |
| 63 | } |
| 64 | pb := readNBytes(src, bytesToRead) |
| 65 | for i := 0; i < bytesToRead; i++ { |
| 66 | val = val * 256 |
| 67 | val += int64(pb[i]) |
| 68 | } |
| 69 | } |
| 70 | return val |
| 71 | } |
| 72 | |
| 73 | func decodeInteger(src *bufio.Reader) int64 { |
| 74 | pb := readByte(src) |
| 75 | major := pb & maskOutAdditionalType |
| 76 | minor := pb & maskOutMajorType |
| 77 | if major != majorTypeUnsignedInt && major != majorTypeNegativeInt { |
| 78 | panic(fmt.Errorf("Major type is: %d in decodeInteger!! (expected 0 or 1)", major)) |
| 79 | } |
| 80 | val := decodeIntAdditonalType(src, minor) |
| 81 | if major == 0 { |
| 82 | return val |
| 83 | } |
| 84 | return (-1 - val) |
| 85 | } |
| 86 | |
| 87 | func decodeFloat(src *bufio.Reader) (float64, int) { |
| 88 | pb := readByte(src) |
| 89 | major := pb & maskOutAdditionalType |
| 90 | minor := pb & maskOutMajorType |
| 91 | if major != majorTypeSimpleAndFloat { |
| 92 | panic(fmt.Errorf("Incorrect Major type is: %d in decodeFloat", major)) |
| 93 | } |
| 94 | |
| 95 | switch minor { |
| 96 | case additionalTypeFloat16: |
| 97 | panic(fmt.Errorf("float16 is not suppported in decodeFloat")) |
| 98 | |
| 99 | case additionalTypeFloat32: |
| 100 | pb := readNBytes(src, 4) |
| 101 | switch string(pb) { |
| 102 | case float32Nan: |
| 103 | return math.NaN(), isFloat32 |
| 104 | case float32PosInfinity: |
| 105 | return math.Inf(0), isFloat32 |
| 106 | case float32NegInfinity: |
| 107 | return math.Inf(-1), isFloat32 |
| 108 | } |
| 109 | n := uint32(0) |
| 110 | for i := 0; i < 4; i++ { |
| 111 | n = n * 256 |
| 112 | n += uint32(pb[i]) |
| 113 | } |
| 114 | val := math.Float32frombits(n) |
| 115 | return float64(val), isFloat32 |
| 116 | case additionalTypeFloat64: |
| 117 | pb := readNBytes(src, 8) |
| 118 | switch string(pb) { |
| 119 | case float64Nan: |
| 120 | return math.NaN(), isFloat64 |
| 121 | case float64PosInfinity: |
| 122 | return math.Inf(0), isFloat64 |
| 123 | case float64NegInfinity: |
| 124 | return math.Inf(-1), isFloat64 |
| 125 | } |
| 126 | n := uint64(0) |
| 127 | for i := 0; i < 8; i++ { |
| 128 | n = n * 256 |
| 129 | n += uint64(pb[i]) |
| 130 | } |
| 131 | val := math.Float64frombits(n) |
| 132 | return val, isFloat64 |
| 133 | } |
| 134 | panic(fmt.Errorf("Invalid Additional Type: %d in decodeFloat", minor)) |
| 135 | } |
| 136 | |
| 137 | func decodeStringComplex(dst []byte, s string, pos uint) []byte { |
| 138 | i := int(pos) |
| 139 | start := 0 |
| 140 | |
| 141 | for i < len(s) { |
| 142 | b := s[i] |
| 143 | if b >= utf8.RuneSelf { |
| 144 | r, size := utf8.DecodeRuneInString(s[i:]) |
| 145 | if r == utf8.RuneError && size == 1 { |
| 146 | // In case of error, first append previous simple characters to |
| 147 | // the byte slice if any and append a replacement character code |
| 148 | // in place of the invalid sequence. |
| 149 | if start < i { |
| 150 | dst = append(dst, s[start:i]...) |
| 151 | } |
| 152 | dst = append(dst, `\ufffd`...) |
| 153 | i += size |
| 154 | start = i |
| 155 | continue |
| 156 | } |
| 157 | i += size |
| 158 | continue |
| 159 | } |
| 160 | if b >= 0x20 && b <= 0x7e && b != '\\' && b != '"' { |
| 161 | i++ |
| 162 | continue |
| 163 | } |
| 164 | // We encountered a character that needs to be encoded. |
| 165 | // Let's append the previous simple characters to the byte slice |
| 166 | // and switch our operation to read and encode the remainder |
| 167 | // characters byte-by-byte. |
| 168 | if start < i { |
| 169 | dst = append(dst, s[start:i]...) |
| 170 | } |
| 171 | switch b { |
| 172 | case '"', '\\': |
| 173 | dst = append(dst, '\\', b) |
| 174 | case '\b': |
| 175 | dst = append(dst, '\\', 'b') |
| 176 | case '\f': |
| 177 | dst = append(dst, '\\', 'f') |
| 178 | case '\n': |
| 179 | dst = append(dst, '\\', 'n') |
| 180 | case '\r': |
| 181 | dst = append(dst, '\\', 'r') |
| 182 | case '\t': |
| 183 | dst = append(dst, '\\', 't') |
| 184 | default: |
| 185 | dst = append(dst, '\\', 'u', '0', '0', hexTable[b>>4], hexTable[b&0xF]) |
| 186 | } |
| 187 | i++ |
| 188 | start = i |
| 189 | } |
| 190 | if start < len(s) { |
| 191 | dst = append(dst, s[start:]...) |
| 192 | } |
| 193 | return dst |
| 194 | } |
| 195 | |
| 196 | func decodeString(src *bufio.Reader, noQuotes bool) []byte { |
| 197 | pb := readByte(src) |
| 198 | major := pb & maskOutAdditionalType |
| 199 | minor := pb & maskOutMajorType |
| 200 | if major != majorTypeByteString { |
| 201 | panic(fmt.Errorf("Major type is: %d in decodeString", major)) |
| 202 | } |
| 203 | result := []byte{} |
| 204 | if !noQuotes { |
| 205 | result = append(result, '"') |
| 206 | } |
| 207 | length := decodeIntAdditonalType(src, minor) |
| 208 | len := int(length) |
| 209 | pbs := readNBytes(src, len) |
| 210 | result = append(result, pbs...) |
| 211 | if noQuotes { |
| 212 | return result |
| 213 | } |
| 214 | return append(result, '"') |
| 215 | } |
| 216 | |
| 217 | func decodeUTF8String(src *bufio.Reader) []byte { |
| 218 | pb := readByte(src) |
| 219 | major := pb & maskOutAdditionalType |
| 220 | minor := pb & maskOutMajorType |
| 221 | if major != majorTypeUtf8String { |
| 222 | panic(fmt.Errorf("Major type is: %d in decodeUTF8String", major)) |
| 223 | } |
| 224 | result := []byte{'"'} |
| 225 | length := decodeIntAdditonalType(src, minor) |
| 226 | len := int(length) |
| 227 | pbs := readNBytes(src, len) |
| 228 | |
| 229 | for i := 0; i < len; i++ { |
| 230 | // Check if the character needs encoding. Control characters, slashes, |
| 231 | // and the double quote need json encoding. Bytes above the ascii |
| 232 | // boundary needs utf8 encoding. |
| 233 | if pbs[i] < 0x20 || pbs[i] > 0x7e || pbs[i] == '\\' || pbs[i] == '"' { |
| 234 | // We encountered a character that needs to be encoded. Switch |
| 235 | // to complex version of the algorithm. |
| 236 | dst := []byte{'"'} |
| 237 | dst = decodeStringComplex(dst, string(pbs), uint(i)) |
| 238 | return append(dst, '"') |
| 239 | } |
| 240 | } |
| 241 | // The string has no need for encoding an therefore is directly |
| 242 | // appended to the byte slice. |
| 243 | result = append(result, pbs...) |
| 244 | return append(result, '"') |
| 245 | } |
| 246 | |
| 247 | func array2Json(src *bufio.Reader, dst io.Writer) { |
| 248 | dst.Write([]byte{'['}) |
| 249 | pb := readByte(src) |
| 250 | major := pb & maskOutAdditionalType |
| 251 | minor := pb & maskOutMajorType |
| 252 | if major != majorTypeArray { |
| 253 | panic(fmt.Errorf("Major type is: %d in array2Json", major)) |
| 254 | } |
| 255 | len := 0 |
| 256 | unSpecifiedCount := false |
| 257 | if minor == additionalTypeInfiniteCount { |
| 258 | unSpecifiedCount = true |
| 259 | } else { |
| 260 | length := decodeIntAdditonalType(src, minor) |
| 261 | len = int(length) |
| 262 | } |
| 263 | for i := 0; unSpecifiedCount || i < len; i++ { |
| 264 | if unSpecifiedCount { |
| 265 | pb, e := src.Peek(1) |
| 266 | if e != nil { |
| 267 | panic(e) |
| 268 | } |
| 269 | if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { |
| 270 | readByte(src) |
| 271 | break |
| 272 | } |
| 273 | } |
| 274 | cbor2JsonOneObject(src, dst) |
| 275 | if unSpecifiedCount { |
| 276 | pb, e := src.Peek(1) |
| 277 | if e != nil { |
| 278 | panic(e) |
| 279 | } |
| 280 | if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { |
| 281 | readByte(src) |
| 282 | break |
| 283 | } |
| 284 | dst.Write([]byte{','}) |
| 285 | } else if i+1 < len { |
| 286 | dst.Write([]byte{','}) |
| 287 | } |
| 288 | } |
| 289 | dst.Write([]byte{']'}) |
| 290 | } |
| 291 | |
| 292 | func map2Json(src *bufio.Reader, dst io.Writer) { |
| 293 | pb := readByte(src) |
| 294 | major := pb & maskOutAdditionalType |
| 295 | minor := pb & maskOutMajorType |
| 296 | if major != majorTypeMap { |
| 297 | panic(fmt.Errorf("Major type is: %d in map2Json", major)) |
| 298 | } |
| 299 | len := 0 |
| 300 | unSpecifiedCount := false |
| 301 | if minor == additionalTypeInfiniteCount { |
| 302 | unSpecifiedCount = true |
| 303 | } else { |
| 304 | length := decodeIntAdditonalType(src, minor) |
| 305 | len = int(length) |
| 306 | } |
| 307 | dst.Write([]byte{'{'}) |
| 308 | for i := 0; unSpecifiedCount || i < len; i++ { |
| 309 | if unSpecifiedCount { |
| 310 | pb, e := src.Peek(1) |
| 311 | if e != nil { |
| 312 | panic(e) |
| 313 | } |
| 314 | if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { |
| 315 | readByte(src) |
| 316 | break |
| 317 | } |
| 318 | } |
| 319 | cbor2JsonOneObject(src, dst) |
| 320 | if i%2 == 0 { |
| 321 | // Even position values are keys. |
| 322 | dst.Write([]byte{':'}) |
| 323 | } else { |
| 324 | if unSpecifiedCount { |
| 325 | pb, e := src.Peek(1) |
| 326 | if e != nil { |
| 327 | panic(e) |
| 328 | } |
| 329 | if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { |
| 330 | readByte(src) |
| 331 | break |
| 332 | } |
| 333 | dst.Write([]byte{','}) |
| 334 | } else if i+1 < len { |
| 335 | dst.Write([]byte{','}) |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | dst.Write([]byte{'}'}) |
| 340 | } |
| 341 | |
| 342 | func decodeTagData(src *bufio.Reader) []byte { |
| 343 | pb := readByte(src) |
| 344 | major := pb & maskOutAdditionalType |
| 345 | minor := pb & maskOutMajorType |
| 346 | if major != majorTypeTags { |
| 347 | panic(fmt.Errorf("Major type is: %d in decodeTagData", major)) |
| 348 | } |
| 349 | switch minor { |
| 350 | case additionalTypeTimestamp: |
| 351 | return decodeTimeStamp(src) |
| 352 | |
| 353 | // Tag value is larger than 256 (so uint16). |
| 354 | case additionalTypeIntUint16: |
| 355 | val := decodeIntAdditonalType(src, minor) |
| 356 | |
| 357 | switch uint16(val) { |
| 358 | case additionalTypeEmbeddedJSON: |
| 359 | pb := readByte(src) |
| 360 | dataMajor := pb & maskOutAdditionalType |
| 361 | if dataMajor != majorTypeByteString { |
| 362 | panic(fmt.Errorf("Unsupported embedded Type: %d in decodeEmbeddedJSON", dataMajor)) |
| 363 | } |
| 364 | src.UnreadByte() |
| 365 | return decodeString(src, true) |
| 366 | |
| 367 | case additionalTypeTagNetworkAddr: |
| 368 | octets := decodeString(src, true) |
| 369 | ss := []byte{'"'} |
| 370 | switch len(octets) { |
| 371 | case 6: // MAC address. |
| 372 | ha := net.HardwareAddr(octets) |
| 373 | ss = append(append(ss, ha.String()...), '"') |
| 374 | case 4: // IPv4 address. |
| 375 | fallthrough |
| 376 | case 16: // IPv6 address. |
| 377 | ip := net.IP(octets) |
| 378 | ss = append(append(ss, ip.String()...), '"') |
| 379 | default: |
| 380 | panic(fmt.Errorf("Unexpected Network Address length: %d (expected 4,6,16)", len(octets))) |
| 381 | } |
| 382 | return ss |
| 383 | |
| 384 | case additionalTypeTagNetworkPrefix: |
| 385 | pb := readByte(src) |
| 386 | if pb != byte(majorTypeMap|0x1) { |
| 387 | panic(fmt.Errorf("IP Prefix is NOT of MAP of 1 elements as expected")) |
| 388 | } |
| 389 | octets := decodeString(src, true) |
| 390 | val := decodeInteger(src) |
| 391 | ip := net.IP(octets) |
| 392 | var mask net.IPMask |
| 393 | pfxLen := int(val) |
| 394 | if len(octets) == 4 { |
| 395 | mask = net.CIDRMask(pfxLen, 32) |
| 396 | } else { |
| 397 | mask = net.CIDRMask(pfxLen, 128) |
| 398 | } |
| 399 | ipPfx := net.IPNet{IP: ip, Mask: mask} |
| 400 | ss := []byte{'"'} |
| 401 | ss = append(append(ss, ipPfx.String()...), '"') |
| 402 | return ss |
| 403 | |
| 404 | case additionalTypeTagHexString: |
| 405 | octets := decodeString(src, true) |
| 406 | ss := []byte{'"'} |
| 407 | for _, v := range octets { |
| 408 | ss = append(ss, hexTable[v>>4], hexTable[v&0x0f]) |
| 409 | } |
| 410 | return append(ss, '"') |
| 411 | |
| 412 | default: |
| 413 | panic(fmt.Errorf("Unsupported Additional Tag Type: %d in decodeTagData", val)) |
| 414 | } |
| 415 | } |
| 416 | panic(fmt.Errorf("Unsupported Additional Type: %d in decodeTagData", minor)) |
| 417 | } |
| 418 | |
| 419 | func decodeTimeStamp(src *bufio.Reader) []byte { |
| 420 | pb := readByte(src) |
| 421 | src.UnreadByte() |
| 422 | tsMajor := pb & maskOutAdditionalType |
| 423 | if tsMajor == majorTypeUnsignedInt || tsMajor == majorTypeNegativeInt { |
| 424 | n := decodeInteger(src) |
| 425 | t := time.Unix(n, 0) |
| 426 | if decodeTimeZone != nil { |
| 427 | t = t.In(decodeTimeZone) |
| 428 | } else { |
| 429 | t = t.In(time.UTC) |
| 430 | } |
| 431 | tsb := []byte{} |
| 432 | tsb = append(tsb, '"') |
| 433 | tsb = t.AppendFormat(tsb, IntegerTimeFieldFormat) |
| 434 | tsb = append(tsb, '"') |
| 435 | return tsb |
| 436 | } else if tsMajor == majorTypeSimpleAndFloat { |
| 437 | n, _ := decodeFloat(src) |
| 438 | secs := int64(n) |
| 439 | n -= float64(secs) |
| 440 | n *= float64(1e9) |
| 441 | t := time.Unix(secs, int64(n)) |
| 442 | if decodeTimeZone != nil { |
| 443 | t = t.In(decodeTimeZone) |
| 444 | } else { |
| 445 | t = t.In(time.UTC) |
| 446 | } |
| 447 | tsb := []byte{} |
| 448 | tsb = append(tsb, '"') |
| 449 | tsb = t.AppendFormat(tsb, NanoTimeFieldFormat) |
| 450 | tsb = append(tsb, '"') |
| 451 | return tsb |
| 452 | } |
| 453 | panic(fmt.Errorf("TS format is neigther int nor float: %d", tsMajor)) |
| 454 | } |
| 455 | |
| 456 | func decodeSimpleFloat(src *bufio.Reader) []byte { |
| 457 | pb := readByte(src) |
| 458 | major := pb & maskOutAdditionalType |
| 459 | minor := pb & maskOutMajorType |
| 460 | if major != majorTypeSimpleAndFloat { |
| 461 | panic(fmt.Errorf("Major type is: %d in decodeSimpleFloat", major)) |
| 462 | } |
| 463 | switch minor { |
| 464 | case additionalTypeBoolTrue: |
| 465 | return []byte("true") |
| 466 | case additionalTypeBoolFalse: |
| 467 | return []byte("false") |
| 468 | case additionalTypeNull: |
| 469 | return []byte("null") |
| 470 | case additionalTypeFloat16: |
| 471 | fallthrough |
| 472 | case additionalTypeFloat32: |
| 473 | fallthrough |
| 474 | case additionalTypeFloat64: |
| 475 | src.UnreadByte() |
| 476 | v, bc := decodeFloat(src) |
| 477 | ba := []byte{} |
| 478 | switch { |
| 479 | case math.IsNaN(v): |
| 480 | return []byte("\"NaN\"") |
| 481 | case math.IsInf(v, 1): |
| 482 | return []byte("\"+Inf\"") |
| 483 | case math.IsInf(v, -1): |
| 484 | return []byte("\"-Inf\"") |
| 485 | } |
| 486 | if bc == isFloat32 { |
| 487 | ba = strconv.AppendFloat(ba, v, 'f', -1, 32) |
| 488 | } else if bc == isFloat64 { |
| 489 | ba = strconv.AppendFloat(ba, v, 'f', -1, 64) |
| 490 | } else { |
| 491 | panic(fmt.Errorf("Invalid Float precision from decodeFloat: %d", bc)) |
| 492 | } |
| 493 | return ba |
| 494 | default: |
| 495 | panic(fmt.Errorf("Invalid Additional Type: %d in decodeSimpleFloat", minor)) |
| 496 | } |
| 497 | } |
| 498 | |
| 499 | func cbor2JsonOneObject(src *bufio.Reader, dst io.Writer) { |
| 500 | pb, e := src.Peek(1) |
| 501 | if e != nil { |
| 502 | panic(e) |
| 503 | } |
| 504 | major := (pb[0] & maskOutAdditionalType) |
| 505 | |
| 506 | switch major { |
| 507 | case majorTypeUnsignedInt: |
| 508 | fallthrough |
| 509 | case majorTypeNegativeInt: |
| 510 | n := decodeInteger(src) |
| 511 | dst.Write([]byte(strconv.Itoa(int(n)))) |
| 512 | |
| 513 | case majorTypeByteString: |
| 514 | s := decodeString(src, false) |
| 515 | dst.Write(s) |
| 516 | |
| 517 | case majorTypeUtf8String: |
| 518 | s := decodeUTF8String(src) |
| 519 | dst.Write(s) |
| 520 | |
| 521 | case majorTypeArray: |
| 522 | array2Json(src, dst) |
| 523 | |
| 524 | case majorTypeMap: |
| 525 | map2Json(src, dst) |
| 526 | |
| 527 | case majorTypeTags: |
| 528 | s := decodeTagData(src) |
| 529 | dst.Write(s) |
| 530 | |
| 531 | case majorTypeSimpleAndFloat: |
| 532 | s := decodeSimpleFloat(src) |
| 533 | dst.Write(s) |
| 534 | } |
| 535 | } |
| 536 | |
| 537 | func moreBytesToRead(src *bufio.Reader) bool { |
| 538 | _, e := src.ReadByte() |
| 539 | if e == nil { |
| 540 | src.UnreadByte() |
| 541 | return true |
| 542 | } |
| 543 | return false |
| 544 | } |
| 545 | |
| 546 | // Cbor2JsonManyObjects decodes all the CBOR Objects read from src |
| 547 | // reader. It keeps on decoding until reader returns EOF (error when reading). |
| 548 | // Decoded string is written to the dst. At the end of every CBOR Object |
| 549 | // newline is written to the output stream. |
| 550 | // |
| 551 | // Returns error (if any) that was encountered during decode. |
| 552 | // The child functions will generate a panic when error is encountered and |
| 553 | // this function will recover non-runtime Errors and return the reason as error. |
| 554 | func Cbor2JsonManyObjects(src io.Reader, dst io.Writer) (err error) { |
| 555 | defer func() { |
| 556 | if r := recover(); r != nil { |
| 557 | if _, ok := r.(runtime.Error); ok { |
| 558 | panic(r) |
| 559 | } |
| 560 | err = r.(error) |
| 561 | } |
| 562 | }() |
| 563 | bufRdr := bufio.NewReader(src) |
| 564 | for moreBytesToRead(bufRdr) { |
| 565 | cbor2JsonOneObject(bufRdr, dst) |
| 566 | dst.Write([]byte("\n")) |
| 567 | } |
| 568 | return nil |
| 569 | } |
| 570 | |
| 571 | // Detect if the bytes to be printed is Binary or not. |
| 572 | func binaryFmt(p []byte) bool { |
| 573 | if len(p) > 0 && p[0] > 0x7F { |
| 574 | return true |
| 575 | } |
| 576 | return false |
| 577 | } |
| 578 | |
| 579 | func getReader(str string) *bufio.Reader { |
| 580 | return bufio.NewReader(strings.NewReader(str)) |
| 581 | } |
| 582 | |
| 583 | // DecodeIfBinaryToString converts a binary formatted log msg to a |
| 584 | // JSON formatted String Log message - suitable for printing to Console/Syslog. |
| 585 | func DecodeIfBinaryToString(in []byte) string { |
| 586 | if binaryFmt(in) { |
| 587 | var b bytes.Buffer |
| 588 | Cbor2JsonManyObjects(strings.NewReader(string(in)), &b) |
| 589 | return b.String() |
| 590 | } |
| 591 | return string(in) |
| 592 | } |
| 593 | |
| 594 | // DecodeObjectToStr checks if the input is a binary format, if so, |
| 595 | // it will decode a single Object and return the decoded string. |
| 596 | func DecodeObjectToStr(in []byte) string { |
| 597 | if binaryFmt(in) { |
| 598 | var b bytes.Buffer |
| 599 | cbor2JsonOneObject(getReader(string(in)), &b) |
| 600 | return b.String() |
| 601 | } |
| 602 | return string(in) |
| 603 | } |
| 604 | |
| 605 | // DecodeIfBinaryToBytes checks if the input is a binary format, if so, |
| 606 | // it will decode all Objects and return the decoded string as byte array. |
| 607 | func DecodeIfBinaryToBytes(in []byte) []byte { |
| 608 | if binaryFmt(in) { |
| 609 | var b bytes.Buffer |
| 610 | Cbor2JsonManyObjects(bytes.NewReader(in), &b) |
| 611 | return b.Bytes() |
| 612 | } |
| 613 | return in |
| 614 | } |