github.com/onosproject/onos-api/go@v0.10.32/onos/config/v3/typedvalue.go (about) 1 // SPDX-FileCopyrightText: 2020-present Open Networking Foundation <info@opennetworking.org> 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package v3 6 7 import ( 8 "encoding/base64" 9 "encoding/binary" 10 "fmt" 11 "math" 12 "math/big" 13 "strconv" 14 "strings" 15 ) 16 17 const ( 18 isPositiveTypeOpt = int32(0) 19 isNegativeTypeOpt = int32(1) 20 ) 21 22 type Width int 23 24 const ( 25 WidthUnknown Width = 1 << (iota + 2) 26 WidthEight 27 WidthSixteen 28 WidthThirtyTwo 29 WidthSixtyFour 30 ) 31 32 // TypedValueMap is an alias for a map of paths and values 33 type TypedValueMap map[string]*TypedValue 34 35 // ValueToString is the String calculated as a Native type 36 // There is already a String() in the protobuf generated code that can't be 37 // overridden 38 func (tv *TypedValue) ValueToString() string { 39 switch tv.Type { 40 case ValueType_EMPTY: 41 return "" 42 case ValueType_STRING: 43 return (*TypedString)(tv).String() 44 case ValueType_INT: 45 return (*TypedInt)(tv).String() 46 case ValueType_UINT: 47 return (*TypedUint)(tv).String() 48 case ValueType_BOOL: 49 return (*TypedBool)(tv).String() 50 case ValueType_DECIMAL: 51 return (*TypedDecimal)(tv).String() 52 case ValueType_FLOAT: 53 return (*TypedFloat)(tv).String() 54 case ValueType_DOUBLE: 55 return (*TypedDouble)(tv).String() 56 case ValueType_BYTES: 57 return (*TypedBytes)(tv).String() 58 case ValueType_LEAFLIST_STRING: 59 return (*TypedLeafListString)(tv).String() 60 case ValueType_LEAFLIST_INT: 61 return (*TypedLeafListInt)(tv).String() 62 case ValueType_LEAFLIST_UINT: 63 return (*TypedLeafListUint)(tv).String() 64 case ValueType_LEAFLIST_BOOL: 65 return (*TypedLeafListBool)(tv).String() 66 case ValueType_LEAFLIST_DECIMAL: 67 return (*TypedLeafListDecimal)(tv).String() 68 case ValueType_LEAFLIST_FLOAT: 69 return (*TypedLeafListFloat)(tv).String() 70 case ValueType_LEAFLIST_BYTES: 71 return (*TypedLeafListBytes)(tv).String() 72 } 73 74 return "" 75 } 76 77 // NewTypedValue creates a TypeValue from a byte[] and type - used in changes.go 78 // For Int and Uint both the width and sign must be given in type opts e.g. [32, 1] 79 func NewTypedValue(bytes []byte, valueType ValueType, typeOpts []uint8) (*TypedValue, error) { 80 switch valueType { 81 case ValueType_EMPTY: 82 return NewTypedValueEmpty(), nil 83 case ValueType_STRING: 84 return NewTypedValueString(string(bytes)), nil 85 case ValueType_INT: 86 if len(typeOpts) != 2 { 87 return nil, fmt.Errorf("number width AND sign must be given for INT as type opts. %v", typeOpts) 88 } 89 if typeOpts[0]/8 < uint8(len(bytes)) { 90 return nil, fmt.Errorf("number width %d must match number of bytes %d for INT", typeOpts[0], len(bytes)) 91 } 92 var bigInt big.Int 93 bigInt.SetBytes(bytes) 94 if len(typeOpts) == 2 && typeOpts[1] != uint8(isPositiveTypeOpt) { 95 // Negative value 96 bigInt.Neg(&bigInt) 97 } 98 return NewTypedValueInt(int(bigInt.Int64()), Width(typeOpts[0])), nil 99 case ValueType_UINT: 100 if len(typeOpts) != 1 { 101 return nil, fmt.Errorf("number width must be given for UINT as type opts. %v", typeOpts) 102 } 103 if typeOpts[0]/8 < uint8(len(bytes)) { 104 return nil, fmt.Errorf("number width %d must match number of bytes %d for INT", typeOpts[0], len(bytes)) 105 } 106 var bigInt big.Int 107 bigInt.SetBytes(bytes) 108 109 return NewTypedValueUint(uint(bigInt.Uint64()), Width(typeOpts[0])), nil 110 case ValueType_BOOL: 111 if len(bytes) != 1 { 112 return nil, fmt.Errorf("expecting 1 byte for BOOL. Got %d", len(bytes)) 113 } 114 value := false 115 if bytes[0] == 1 { 116 value = true 117 } 118 return NewTypedValueBool(value), nil 119 case ValueType_DECIMAL: 120 if len(typeOpts) != 2 { 121 return nil, fmt.Errorf("precision AND sign must be given for DECIMAL as type opts. %v", typeOpts) 122 } 123 precision := typeOpts[0] 124 var bigInt big.Int 125 bigInt.SetBytes(bytes) 126 if len(typeOpts) == 2 && typeOpts[1] != uint8(isPositiveTypeOpt) { 127 // Negative value 128 bigInt.Neg(&bigInt) 129 } 130 return NewTypedValueDecimal(bigInt.Int64(), precision), nil 131 case ValueType_FLOAT: 132 if len(bytes) != 8 { 133 return nil, fmt.Errorf("expecting 8 bytes for FLOAT. Got %d", len(bytes)) 134 } 135 return NewTypedValueFloat(float64(math.Float64frombits(binary.LittleEndian.Uint64(bytes)))), nil 136 case ValueType_DOUBLE: 137 return NewTypedValueDouble(float64(math.Float64frombits(binary.LittleEndian.Uint64(bytes)))), nil 138 case ValueType_BYTES: 139 return NewTypedValueBytes(bytes), nil 140 case ValueType_LEAFLIST_STRING: 141 return caseValueTypeLeafListSTRING(bytes) 142 case ValueType_LEAFLIST_INT: 143 return caseValueTypeLeafListINT(bytes, typeOpts) 144 case ValueType_LEAFLIST_UINT: 145 return caseValueTypeLeafListUINT(bytes, typeOpts) 146 case ValueType_LEAFLIST_BOOL: 147 return caseValueTypeLeafListBOOL(bytes) 148 case ValueType_LEAFLIST_DECIMAL: 149 return caseValueTypeLeafListDECIMAL(bytes, typeOpts) 150 case ValueType_LEAFLIST_FLOAT: 151 return caseValueTypeLeafListFLOAT(bytes) 152 case ValueType_LEAFLIST_DOUBLE: 153 return caseValueTypeLeafListDOUBLE(bytes) 154 case ValueType_LEAFLIST_BYTES: 155 return caseValueTypeLeafListBYTES(bytes, typeOpts) 156 } 157 158 return nil, fmt.Errorf("unexpected type %d", valueType) 159 } 160 161 // caseValueTypeLeafListSTRING is moved out of NewTypedValue because of gocyclo 162 func caseValueTypeLeafListSTRING(bytes []byte) (*TypedValue, error) { 163 stringList := make([]string, 0) 164 buf := make([]byte, 0) 165 for _, b := range bytes { 166 if b != 0x1D { 167 buf = append(buf, b) 168 } else { 169 stringList = append(stringList, string(buf)) 170 buf = make([]byte, 0) 171 } 172 } 173 stringList = append(stringList, string(buf)) 174 return NewLeafListStringTv(stringList), nil 175 } 176 177 // caseValueTypeLeafListINT is moved out of NewTypedValue because of gocyclo 178 func caseValueTypeLeafListINT(bytes []byte, typeOpts []uint8) (*TypedValue, error) { 179 count := (len(typeOpts) - 1) / 2 180 if count < 1 { 181 return nil, fmt.Errorf("unexpected #type opts. Expect 1 for width and then a pair per entry [len bytes, negative]") 182 } 183 intList := make([]int64, 0) 184 width := Width(typeOpts[0]) 185 var byteCounter uint32 = 0 186 for i := 0; i < count; i++ { 187 v := bytes[byteCounter : byteCounter+uint32(typeOpts[1+i*2])] 188 byteCounter += uint32(typeOpts[1+i*2]) 189 var bigInt big.Int 190 bigInt.SetBytes(v) 191 negative := typeOpts[1+i*2+1] 192 if negative != uint8(isPositiveTypeOpt) { 193 bigInt.Neg(&bigInt) 194 } 195 intList = append(intList, bigInt.Int64()) 196 } 197 return NewLeafListIntTv(intList, width), nil 198 } 199 200 // caseValueTypeLeafListUINT is moved out of NewTypedValue because of gocyclo 201 func caseValueTypeLeafListUINT(bytes []byte, typeOpts []uint8) (*TypedValue, error) { 202 count := (len(typeOpts) - 1) 203 if count < 1 { 204 return nil, fmt.Errorf("unexpected #type opts. Expect 1 for width and then a value per entry [len bytes]") 205 } 206 uintList := make([]uint64, 0) 207 width := Width(typeOpts[0]) 208 var byteCounter uint32 = 0 209 for i := 0; i < count; i++ { 210 v := bytes[byteCounter : byteCounter+uint32(typeOpts[1+i])] 211 byteCounter += uint32(typeOpts[1+i]) 212 var bigInt big.Int 213 bigInt.SetBytes(v) 214 uintList = append(uintList, bigInt.Uint64()) 215 } 216 217 return NewLeafListUintTv(uintList, width), nil 218 } 219 220 // caseValueTypeLeafListBOOL is moved out of NewTypedValue because of gocyclo 221 func caseValueTypeLeafListBOOL(bytes []byte) (*TypedValue, error) { 222 count := len(bytes) 223 bools := make([]bool, count) 224 for i, v := range bytes { 225 if v == 1 { 226 bools[i] = true 227 } 228 } 229 return NewLeafListBoolTv(bools), nil 230 } 231 232 // caseValueTypeLeafListDECIMAL is moved out of NewTypedValue because of gocyclo 233 // First typeOpt is precision. Expect a pair of type opts per entry [len bytes, negative] 234 func caseValueTypeLeafListDECIMAL(bytes []byte, typeOpts []uint8) (*TypedValue, error) { 235 count := (len(typeOpts) - 1) / 2 236 if count < 1 { 237 return nil, fmt.Errorf("unexpected #type opts. Expect 1 for precision and then a pair per entry [len bytes, negative]") 238 } 239 digitsList := make([]int64, 0) 240 precision := typeOpts[0] 241 var byteCounter uint32 = 0 242 for i := 0; i < count; i++ { 243 v := bytes[byteCounter : byteCounter+uint32(typeOpts[1+i*2])] 244 byteCounter += uint32(typeOpts[1+i*2]) 245 var bigInt big.Int 246 bigInt.SetBytes(v) 247 negative := typeOpts[1+i*2+1] 248 if negative != uint8(isPositiveTypeOpt) { 249 bigInt.Neg(&bigInt) 250 } 251 digitsList = append(digitsList, bigInt.Int64()) 252 } 253 return NewLeafListDecimalTv(digitsList, precision), nil 254 } 255 256 // caseValueTypeLeafListFLOAT is moved out of NewTypedValue because of gocyclo 257 func caseValueTypeLeafListFLOAT(bytes []byte) (*TypedValue, error) { 258 count := len(bytes) / 8 259 float32s := make([]float32, 0) 260 261 for i := 0; i < count; i++ { 262 v := bytes[i*8 : i*8+8] 263 float32s = append(float32s, float32(math.Float64frombits(binary.LittleEndian.Uint64(v)))) 264 } 265 return NewLeafListFloatTv(float32s), nil 266 } 267 268 // caseValueTypeLeafListDOUBLE is moved out of NewTypedValue because of gocyclo 269 func caseValueTypeLeafListDOUBLE(bytes []byte) (*TypedValue, error) { 270 count := len(bytes) / 8 271 doubles := make([]float64, 0) 272 273 for i := 0; i < count; i++ { 274 v := bytes[i*8 : i*8+8] 275 doubles = append(doubles, float64(math.Float64frombits(binary.LittleEndian.Uint64(v)))) 276 } 277 return NewLeafListDoubleTv(doubles), nil 278 } 279 280 // caseValueTypeLeafListBYTES is moved out of NewTypedValue because of gocyclo 281 func caseValueTypeLeafListBYTES(bytes []byte, typeOpts []uint8) (*TypedValue, error) { 282 if len(typeOpts) < 1 { 283 return nil, fmt.Errorf("expecting 1 typeopt for LeafListBytes. Got %d", len(typeOpts)) 284 } 285 byteArrays := make([][]byte, 0) 286 buf := make([]byte, 0) 287 idx := 0 288 startAt := 0 289 for i, b := range bytes { 290 valueLen := typeOpts[idx] 291 if i-startAt == int(valueLen) { 292 byteArrays = append(byteArrays, buf) 293 buf = make([]byte, 0) 294 idx = idx + 1 295 if idx >= len(typeOpts) { 296 return nil, fmt.Errorf("not enough typeOpts provided - found %d need at least %d", len(typeOpts), idx+1) 297 } 298 startAt = startAt + int(valueLen) 299 } 300 buf = append(buf, b) 301 } 302 byteArrays = append(byteArrays, buf) 303 return NewLeafListBytesTv(byteArrays), nil 304 } 305 306 //////////////////////////////////////////////////////////////////////////////// 307 // TypedEmpty 308 //////////////////////////////////////////////////////////////////////////////// 309 310 // TypedEmpty for an empty value 311 type TypedEmpty TypedValue 312 313 // NewTypedValueEmpty decodes an empty object 314 func NewTypedValueEmpty() *TypedValue { 315 return (*TypedValue)(newEmpty()) 316 } 317 318 // newEmpty creates an instance of the Empty type 319 func newEmpty() *TypedEmpty { 320 typedEmpty := TypedEmpty{ 321 Bytes: make([]byte, 0), 322 Type: ValueType_EMPTY, 323 } 324 return &typedEmpty 325 } 326 327 // ValueType gives the value type 328 func (tv *TypedEmpty) ValueType() ValueType { 329 return tv.Type 330 } 331 332 func (tv *TypedEmpty) String() string { 333 return "" 334 } 335 336 //////////////////////////////////////////////////////////////////////////////// 337 // TypedString 338 //////////////////////////////////////////////////////////////////////////////// 339 340 // TypedString for a string value 341 type TypedString TypedValue 342 343 // NewTypedValueString decodes string value in to an object 344 func NewTypedValueString(value string) *TypedValue { 345 return (*TypedValue)(newString(value)) 346 } 347 348 // newString decodes string value in to a String type 349 func newString(value string) *TypedString { 350 typedString := TypedString{ 351 Bytes: []byte(value), 352 Type: ValueType_STRING, 353 } 354 return &typedString 355 } 356 357 // ValueType gives the value type 358 func (tv *TypedString) ValueType() ValueType { 359 return tv.Type 360 } 361 362 func (tv *TypedString) String() string { 363 return string(tv.Bytes) 364 } 365 366 //////////////////////////////////////////////////////////////////////////////// 367 // TypedInt 368 //////////////////////////////////////////////////////////////////////////////// 369 370 // TypedInt for an int value 371 type TypedInt TypedValue 372 373 // NewTypedValueInt decodes an int value in to an object 374 func NewTypedValueInt(value int, width Width) *TypedValue { 375 return (*TypedValue)(newInt(big.NewInt(int64(value)), width)) 376 } 377 378 func newInt(value *big.Int, width Width) *TypedInt { 379 var isNegative int32 = isPositiveTypeOpt 380 if value.Sign() < 0 { 381 isNegative = isNegativeTypeOpt 382 } 383 typedInt := TypedInt{ 384 Bytes: value.Bytes(), 385 Type: ValueType_INT, 386 TypeOpts: []int32{int32(width), isNegative}, 387 } 388 return &typedInt 389 } 390 391 // ValueType gives the value type 392 func (tv *TypedInt) ValueType() ValueType { 393 return tv.Type 394 } 395 396 func (tv *TypedInt) String() string { 397 return fmt.Sprintf("%d", tv.Int()) 398 } 399 400 // Int extracts the integer value 401 func (tv *TypedInt) Int() int { 402 var x big.Int 403 x.SetBytes(tv.Bytes) 404 if len(tv.TypeOpts) > 1 && tv.TypeOpts[1] == 1 { 405 x.Neg(&x) 406 } 407 return int(x.Int64()) 408 } 409 410 //////////////////////////////////////////////////////////////////////////////// 411 // TypedUint 412 //////////////////////////////////////////////////////////////////////////////// 413 414 // TypedUint for a uint value 415 type TypedUint TypedValue 416 417 // NewTypedValueUint decodes a uint value in to an object 418 func NewTypedValueUint(value uint, width Width) *TypedValue { 419 var bigInt big.Int 420 bigInt.SetUint64(uint64(value)) 421 return (*TypedValue)(newUint(&bigInt, width)) 422 } 423 424 // newUint decodes a uint value in to a Uint type 425 func newUint(value *big.Int, width Width) *TypedUint { 426 typedUint64 := TypedUint{ 427 Bytes: value.Bytes(), 428 Type: ValueType_UINT, 429 TypeOpts: []int32{int32(width)}, 430 } 431 return &typedUint64 432 } 433 434 // ValueType gives the value type 435 func (tv *TypedUint) ValueType() ValueType { 436 return tv.Type 437 } 438 439 func (tv *TypedUint) String() string { 440 return fmt.Sprintf("%d", tv.Uint()) 441 } 442 443 // Uint extracts the unsigned integer value 444 func (tv *TypedUint) Uint() uint { 445 var bigInt big.Int 446 bigInt.SetBytes(tv.Bytes) 447 return uint(bigInt.Uint64()) 448 } 449 450 //////////////////////////////////////////////////////////////////////////////// 451 // TypedBool 452 //////////////////////////////////////////////////////////////////////////////// 453 454 // TypedBool for an int value 455 type TypedBool TypedValue 456 457 // NewTypedValueBool decodes a bool value in to an object 458 func NewTypedValueBool(value bool) *TypedValue { 459 return (*TypedValue)(newBool(value)) 460 } 461 462 // newBool decodes a bool value in to an object 463 func newBool(value bool) *TypedBool { 464 buf := make([]byte, 1) 465 if value { 466 buf[0] = 1 467 } 468 typedBool := TypedBool{ 469 Bytes: buf, 470 Type: ValueType_BOOL, 471 } 472 return &typedBool 473 } 474 475 // ValueType gives the value type 476 func (tv *TypedBool) ValueType() ValueType { 477 return tv.Type 478 } 479 480 func (tv *TypedBool) String() string { 481 if tv.Bytes[0] == 1 { 482 return "true" 483 } 484 return "false" 485 } 486 487 // Bool extracts the unsigned bool value 488 func (tv *TypedBool) Bool() bool { 489 return tv.Bytes[0] == 1 490 } 491 492 //////////////////////////////////////////////////////////////////////////////// 493 // TypedDecimal 494 //////////////////////////////////////////////////////////////////////////////// 495 496 // TypedDecimal for a decimal64 value 497 type TypedDecimal TypedValue 498 499 // NewTypedValueDecimal decodes a decimal value in to an object 500 func NewTypedValueDecimal(digits int64, precision uint8) *TypedValue { 501 return (*TypedValue)(newDecimal(big.NewInt(digits), precision)) 502 } 503 504 // newDecimal decodes a decimal value in to a Decimal type 505 func newDecimal(digits *big.Int, precision uint8) *TypedDecimal { 506 var isNegative int32 = isPositiveTypeOpt 507 if digits.Sign() < 0 { 508 isNegative = isNegativeTypeOpt 509 } 510 typedDecimal64 := TypedDecimal{ 511 Bytes: digits.Bytes(), 512 Type: ValueType_DECIMAL, 513 TypeOpts: []int32{int32(precision), isNegative}, 514 } 515 return &typedDecimal64 516 } 517 518 // ValueType gives the value type 519 func (tv *TypedDecimal) ValueType() ValueType { 520 return tv.Type 521 } 522 523 func (tv *TypedDecimal) String() string { 524 return strDecimal64(tv.Decimal64()) 525 } 526 527 // Decimal64 extracts the unsigned decimal value 528 func (tv *TypedDecimal) Decimal64() (int64, uint8) { 529 if len(tv.TypeOpts) > 0 { 530 precision := tv.TypeOpts[0] 531 var positiveMultiplier int64 = 1 532 if len(tv.TypeOpts) > 1 && tv.TypeOpts[1] == 1 { 533 positiveMultiplier = -1 534 } 535 var value big.Int 536 value.SetBytes(tv.Bytes) 537 return value.Int64() * positiveMultiplier, uint8(precision) 538 } 539 return 0, 0 540 } 541 542 // Float extracts the unsigned decimal value as a float 543 func (tv *TypedDecimal) Float() float64 { 544 floatVal, _ := strconv.ParseFloat(strDecimal64(tv.Decimal64()), 64) 545 return floatVal 546 } 547 548 //////////////////////////////////////////////////////////////////////////////// 549 // TypedFloat 550 //////////////////////////////////////////////////////////////////////////////// 551 552 // TypedFloat for a float value 553 type TypedFloat TypedValue 554 555 // NewTypedValueFloat decodes a decimal value in to an object 556 func NewTypedValueFloat(value float64) *TypedValue { 557 return (*TypedValue)(newFloat(big.NewFloat(value))) 558 } 559 560 // newFloat decodes a decimal value in to a Bool type 561 func newFloat(value *big.Float) *TypedFloat { 562 bytes, _ := value.GobEncode() 563 typedFloat := TypedFloat{ 564 Bytes: bytes, 565 Type: ValueType_FLOAT, 566 } 567 return &typedFloat 568 } 569 570 // ValueType gives the value type 571 func (tv *TypedFloat) ValueType() ValueType { 572 return tv.Type 573 } 574 575 func (tv *TypedFloat) String() string { 576 return fmt.Sprintf("%f", tv.Float32()) 577 } 578 579 // Float32 extracts the float value 580 func (tv *TypedFloat) Float32() float32 { 581 if len(tv.Bytes) == 0 { 582 return 0.0 583 } 584 var value big.Float 585 _ = value.GobDecode(tv.Bytes) 586 flt32, _ := value.Float32() 587 return flt32 588 } 589 590 //////////////////////////////////////////////////////////////////////////////// 591 // TypedDouble 592 //////////////////////////////////////////////////////////////////////////////// 593 594 // TypedDouble for a float value 595 type TypedDouble TypedValue 596 597 // NewTypedValueDouble decodes a decimal value in to an object 598 func NewTypedValueDouble(value float64) *TypedValue { 599 return (*TypedValue)(newDouble(big.NewFloat(value))) 600 } 601 602 // newDouble decodes a decimal value in to a Bool type 603 func newDouble(value *big.Float) *TypedDouble { 604 bytes, _ := value.GobEncode() 605 typedDouble := TypedDouble{ 606 Bytes: bytes, 607 Type: ValueType_DOUBLE, 608 } 609 return &typedDouble 610 } 611 612 // ValueType gives the value type 613 func (tv *TypedDouble) ValueType() ValueType { 614 return tv.Type 615 } 616 617 func (tv *TypedDouble) String() string { 618 return fmt.Sprintf("%f", tv.Double()) 619 } 620 621 // Double extracts the float value 622 func (tv *TypedDouble) Double() float64 { 623 if len(tv.Bytes) == 0 { 624 return 0.0 625 } 626 var value big.Float 627 _ = value.GobDecode(tv.Bytes) 628 double, _ := value.Float64() 629 return double 630 } 631 632 //////////////////////////////////////////////////////////////////////////////// 633 // TypedBytes 634 //////////////////////////////////////////////////////////////////////////////// 635 636 // TypedBytes for a float value 637 type TypedBytes TypedValue 638 639 // NewTypedValueBytes decodes an array of bytes in to an object 640 func NewTypedValueBytes(value []byte) *TypedValue { 641 return (*TypedValue)(newBytes(value)) 642 } 643 644 // newBytes decodes an array of bytes in to a Bytes type 645 func newBytes(value []byte) *TypedBytes { 646 typedFloat := TypedBytes{ 647 Bytes: value, 648 Type: ValueType_BYTES, 649 TypeOpts: []int32{int32(len(value))}, 650 } 651 return &typedFloat 652 } 653 654 // ValueType gives the value type 655 func (tv *TypedBytes) ValueType() ValueType { 656 return tv.Type 657 } 658 659 func (tv *TypedBytes) String() string { 660 return base64.StdEncoding.EncodeToString(tv.Bytes) 661 } 662 663 // ByteArray extracts the bytes value 664 func (tv *TypedBytes) ByteArray() []byte { 665 return tv.Bytes 666 } 667 668 //////////////////////////////////////////////////////////////////////////////// 669 // TypedLeafListString 670 //////////////////////////////////////////////////////////////////////////////// 671 672 // TypedLeafListString for a string leaf list 673 type TypedLeafListString TypedValue 674 675 // NewLeafListStringTv decodes string values in to an object 676 func NewLeafListStringTv(values []string) *TypedValue { 677 return (*TypedValue)(newLeafListString(values)) 678 } 679 680 // newLeafListString decodes string values in to an Leaf list type 681 func newLeafListString(values []string) *TypedLeafListString { 682 first := true 683 bytes := make([]byte, 0) 684 for _, v := range values { 685 if first { 686 first = false 687 } else { 688 bytes = append(bytes, 0x1D) // Group separator 689 } 690 bytes = append(bytes, []byte(v)...) 691 } 692 typedLeafListString := TypedLeafListString{ 693 Bytes: bytes, 694 Type: ValueType_LEAFLIST_STRING, 695 } 696 return &typedLeafListString 697 } 698 699 // ValueType gives the value type 700 func (tv *TypedLeafListString) ValueType() ValueType { 701 return tv.Type 702 } 703 704 func (tv *TypedLeafListString) String() string { 705 return strings.Join(tv.List(), ",") 706 } 707 708 // List extracts the leaf list values 709 func (tv *TypedLeafListString) List() []string { 710 stringList := make([]string, 0) 711 buf := make([]byte, 0) 712 for _, b := range tv.Bytes { 713 if b != 0x1D { 714 buf = append(buf, b) 715 } else { 716 stringList = append(stringList, string(buf)) 717 buf = make([]byte, 0) 718 } 719 } 720 stringList = append(stringList, string(buf)) 721 return stringList 722 } 723 724 //////////////////////////////////////////////////////////////////////////////// 725 // TypedLeafListInt 726 //////////////////////////////////////////////////////////////////////////////// 727 728 // TypedLeafListInt for an int leaf list 729 type TypedLeafListInt TypedValue 730 731 // NewLeafListIntTv decodes int values in to an object 732 func NewLeafListIntTv(values []int64, width Width) *TypedValue { 733 valuesBi := make([]*big.Int, 0) 734 for _, v := range values { 735 valuesBi = append(valuesBi, big.NewInt(v)) 736 } 737 return (*TypedValue)(newLeafListInt(valuesBi, width)) 738 } 739 740 // newLeafListInt decodes int values in to a Leaf list type 741 func newLeafListInt(values []*big.Int, width Width) *TypedLeafListInt { 742 bytes := make([]byte, 0) 743 typeOpts := make([]int32, 0) 744 typeOpts = append(typeOpts, int32(width)) 745 for _, v := range values { 746 var isNegative int32 = isPositiveTypeOpt 747 if v.Sign() < 0 { 748 isNegative = isNegativeTypeOpt 749 } 750 typeOpts = append(typeOpts, int32(len(v.Bytes()))) 751 typeOpts = append(typeOpts, isNegative) 752 bytes = append(bytes, v.Bytes()...) 753 } 754 typedLeafListInt := TypedLeafListInt{ 755 Bytes: bytes, 756 Type: ValueType_LEAFLIST_INT, 757 TypeOpts: typeOpts, 758 } 759 return &typedLeafListInt 760 } 761 762 // ValueType gives the value type 763 func (tv *TypedLeafListInt) ValueType() ValueType { 764 return tv.Type 765 } 766 767 func (tv *TypedLeafListInt) String() string { 768 intValues, width := tv.List() 769 return fmt.Sprintf("%v %d", intValues, width) 770 } 771 772 // List extracts the leaf list values 773 func (tv *TypedLeafListInt) List() ([]int64, Width) { 774 count := (len(tv.TypeOpts) - 1) / 2 775 776 intList := make([]int64, 0) 777 width := tv.TypeOpts[0] 778 var byteCounter int32 = 0 779 for i := 0; i < count; i++ { 780 v := tv.Bytes[byteCounter : byteCounter+tv.TypeOpts[1+i*2]] 781 byteCounter = byteCounter + tv.TypeOpts[1+i*2] 782 var bigInt big.Int 783 bigInt.SetBytes(v) 784 negative := tv.TypeOpts[1+i*2+1] 785 if negative != isPositiveTypeOpt { 786 bigInt.Neg(&bigInt) 787 } 788 intList = append(intList, bigInt.Int64()) 789 } 790 791 return intList, Width(width) 792 } 793 794 //////////////////////////////////////////////////////////////////////////////// 795 // TypedLeafListUint 796 //////////////////////////////////////////////////////////////////////////////// 797 798 // TypedLeafListUint for an uint leaf list 799 type TypedLeafListUint TypedValue 800 801 // NewLeafListUintTv decodes uint values in to a Leaf list 802 func NewLeafListUintTv(values []uint64, width Width) *TypedValue { 803 valuesBi := make([]*big.Int, 0) 804 for _, v := range values { 805 var bigUint big.Int 806 bigUint.SetUint64(v) 807 valuesBi = append(valuesBi, &bigUint) 808 } 809 810 return (*TypedValue)(newLeafListUint(valuesBi, width)) 811 } 812 813 // newLeafListUint decodes uint values in to a Leaf list type 814 func newLeafListUint(values []*big.Int, width Width) *TypedLeafListUint { 815 bytes := make([]byte, 0) 816 typeOpts := make([]int32, 0) 817 typeOpts = append(typeOpts, int32(width)) 818 for _, v := range values { 819 typeOpts = append(typeOpts, int32(len(v.Bytes()))) 820 bytes = append(bytes, v.Bytes()...) 821 } 822 typedLeafListUint := TypedLeafListUint{ 823 Bytes: bytes, 824 Type: ValueType_LEAFLIST_UINT, 825 TypeOpts: typeOpts, 826 } 827 return &typedLeafListUint 828 } 829 830 // ValueType gives the value type 831 func (tv *TypedLeafListUint) ValueType() ValueType { 832 return tv.Type 833 } 834 835 func (tv *TypedLeafListUint) String() string { 836 intValues, width := tv.List() 837 return fmt.Sprintf("%v %d", intValues, width) 838 } 839 840 // List extracts the leaf list values 841 func (tv *TypedLeafListUint) List() ([]uint64, Width) { 842 count := len(tv.TypeOpts) - 1 843 844 uintList := make([]uint64, 0) 845 width := tv.TypeOpts[0] 846 var byteCounter int32 = 0 847 for i := 0; i < count; i++ { 848 v := tv.Bytes[byteCounter : byteCounter+tv.TypeOpts[1+i]] 849 byteCounter = byteCounter + tv.TypeOpts[1+i] 850 var bigInt big.Int 851 bigInt.SetBytes(v) 852 uintList = append(uintList, bigInt.Uint64()) 853 } 854 855 return uintList, Width(width) 856 } 857 858 //////////////////////////////////////////////////////////////////////////////// 859 // TypedLeafListBool 860 //////////////////////////////////////////////////////////////////////////////// 861 862 // TypedLeafListBool for an bool leaf list 863 type TypedLeafListBool TypedValue 864 865 // NewLeafListBoolTv decodes bool values in to an object 866 func NewLeafListBoolTv(values []bool) *TypedValue { 867 return (*TypedValue)(newLeafListBool(values)) 868 } 869 870 // newLeafListBool decodes bool values in to a Leaf list type 871 func newLeafListBool(values []bool) *TypedLeafListBool { 872 count := len(values) 873 bytes := make([]byte, count) 874 for i, b := range values { 875 // just use one byte per bool - inefficient but not worth the hassle 876 var intval uint8 877 if b { 878 intval = 1 879 } 880 bytes[i] = intval 881 } 882 typedLeafListBool := TypedLeafListBool{ 883 Bytes: bytes, 884 Type: ValueType_LEAFLIST_BOOL, 885 } 886 return &typedLeafListBool 887 } 888 889 // ValueType gives the value type 890 func (tv *TypedLeafListBool) ValueType() ValueType { 891 return tv.Type 892 } 893 894 func (tv *TypedLeafListBool) String() string { 895 return fmt.Sprintf("%v", tv.List()) 896 } 897 898 // List extracts the leaf list values 899 func (tv *TypedLeafListBool) List() []bool { 900 count := len(tv.Bytes) 901 bools := make([]bool, count) 902 for i, v := range tv.Bytes { 903 if v == 1 { 904 bools[i] = true 905 } 906 } 907 908 return bools 909 } 910 911 //////////////////////////////////////////////////////////////////////////////// 912 // TypedLeafListDecimal 913 //////////////////////////////////////////////////////////////////////////////// 914 915 // TypedLeafListDecimal for a decimal leaf list 916 type TypedLeafListDecimal TypedValue 917 918 // NewLeafListDecimalTv decodes decimal values in to a Leaf list 919 func NewLeafListDecimalTv(digits []int64, precision uint8) *TypedValue { 920 digitsBi := make([]*big.Int, 0) 921 for _, d := range digits { 922 digitsBi = append(digitsBi, big.NewInt(d)) 923 } 924 return (*TypedValue)(newLeafListDecimal(digitsBi, precision)) 925 } 926 927 // newLeafListDecimal decodes decimal values in to a Leaf list type 928 func newLeafListDecimal(digits []*big.Int, precision uint8) *TypedLeafListDecimal { 929 bytes := make([]byte, 0) 930 typeOpts := make([]int32, 0) 931 typeOpts = append(typeOpts, int32(precision)) 932 for _, d := range digits { 933 typeOpts = append(typeOpts, int32(len(d.Bytes()))) 934 var isNegative int32 = isPositiveTypeOpt 935 if d.Sign() < 0 { 936 isNegative = isNegativeTypeOpt 937 } 938 typeOpts = append(typeOpts, isNegative) 939 bytes = append(bytes, d.Bytes()...) 940 } 941 typedLeafListDecimal := TypedLeafListDecimal{ 942 Bytes: bytes, 943 Type: ValueType_LEAFLIST_DECIMAL, 944 TypeOpts: typeOpts, 945 } 946 return &typedLeafListDecimal 947 } 948 949 // ValueType gives the value type 950 func (tv *TypedLeafListDecimal) ValueType() ValueType { 951 return tv.Type 952 } 953 954 func (tv *TypedLeafListDecimal) String() string { 955 digits, precision := tv.List() 956 return fmt.Sprintf("%v %d", digits, precision) 957 } 958 959 // List extracts the leaf list values 960 func (tv *TypedLeafListDecimal) List() ([]int64, uint8) { 961 count := (len(tv.TypeOpts) - 1) / 2 962 963 digitsList := make([]int64, 0) 964 precision := uint8(tv.TypeOpts[0]) 965 var byteCounter int32 = 0 966 for i := 0; i < count; i++ { 967 v := tv.Bytes[byteCounter : byteCounter+tv.TypeOpts[1+i*2]] 968 byteCounter = byteCounter + tv.TypeOpts[1+i*2] 969 var bigInt big.Int 970 bigInt.SetBytes(v) 971 negative := tv.TypeOpts[1+i*2+1] 972 if negative != isPositiveTypeOpt { 973 bigInt.Neg(&bigInt) 974 } 975 digitsList = append(digitsList, bigInt.Int64()) 976 } 977 978 return digitsList, precision 979 } 980 981 // ListFloat extracts the leaf list values as floats 982 func (tv *TypedLeafListDecimal) ListFloat() []float64 { 983 digits, precision := tv.List() 984 floatList := make([]float64, len(digits)) 985 for i, d := range digits { 986 floatList[i] = float64(d) / math.Pow(10, float64(precision)) 987 } 988 989 return floatList 990 } 991 992 //////////////////////////////////////////////////////////////////////////////// 993 // TypedLeafListFloat 994 //////////////////////////////////////////////////////////////////////////////// 995 996 // TypedLeafListFloat for a decimal leaf list 997 type TypedLeafListFloat TypedValue 998 999 // NewLeafListFloatTv decodes float values in to a Leaf list 1000 func NewLeafListFloatTv(values []float32) *TypedValue { 1001 return (*TypedValue)(newLeafListFloat(values)) 1002 } 1003 1004 // newLeafListFloat decodes float values in to a Leaf list type 1005 func newLeafListFloat(values []float32) *TypedLeafListFloat { 1006 bytes := make([]byte, 0) 1007 for _, f := range values { 1008 buf := make([]byte, 8) 1009 binary.LittleEndian.PutUint64(buf, math.Float64bits(float64(f))) 1010 bytes = append(bytes, buf...) 1011 } 1012 typedLeafListFloat := TypedLeafListFloat{ 1013 Bytes: bytes, 1014 Type: ValueType_LEAFLIST_FLOAT, 1015 } 1016 return &typedLeafListFloat 1017 } 1018 1019 // ValueType gives the value type 1020 func (tv *TypedLeafListFloat) ValueType() ValueType { 1021 return tv.Type 1022 } 1023 1024 func (tv *TypedLeafListFloat) String() string { 1025 listStr := make([]string, 0) 1026 for _, f := range tv.List() { 1027 listStr = append(listStr, fmt.Sprintf("%f", f)) 1028 } 1029 1030 return strings.Join(listStr, ",") 1031 } 1032 1033 // List extracts the leaf list values 1034 func (tv *TypedLeafListFloat) List() []float32 { 1035 count := len(tv.Bytes) / 8 1036 float32s := make([]float32, 0) 1037 1038 for i := 0; i < count; i++ { 1039 v := tv.Bytes[i*8 : i*8+8] 1040 float32s = append(float32s, float32(math.Float64frombits(binary.LittleEndian.Uint64(v)))) 1041 } 1042 1043 return float32s 1044 } 1045 1046 //////////////////////////////////////////////////////////////////////////////// 1047 // TypedLeafListDouble 1048 //////////////////////////////////////////////////////////////////////////////// 1049 1050 // TypedLeafListDouble for a Double leaf list 1051 type TypedLeafListDouble TypedValue 1052 1053 // NewLeafListDoubleTv decodes double values in to a Leaf list 1054 func NewLeafListDoubleTv(values []float64) *TypedValue { 1055 return (*TypedValue)(newLeafListDouble(values)) 1056 } 1057 1058 // newLeafListDouble decodes double values in to a Leaf list type 1059 func newLeafListDouble(values []float64) *TypedLeafListDouble { 1060 bytes := make([]byte, 0) 1061 for _, f := range values { 1062 buf := make([]byte, 8) 1063 binary.LittleEndian.PutUint64(buf, math.Float64bits(float64(f))) 1064 bytes = append(bytes, buf...) 1065 } 1066 typedLeafListDouble := TypedLeafListDouble{ 1067 Bytes: bytes, 1068 Type: ValueType_LEAFLIST_DOUBLE, 1069 } 1070 return &typedLeafListDouble 1071 } 1072 1073 // ValueType gives the value type 1074 func (tv *TypedLeafListDouble) ValueType() ValueType { 1075 return tv.Type 1076 } 1077 1078 func (tv *TypedLeafListDouble) String() string { 1079 listStr := make([]string, 0) 1080 for _, f := range tv.ListDouble() { 1081 listStr = append(listStr, fmt.Sprintf("%f", f)) 1082 } 1083 1084 return strings.Join(listStr, ",") 1085 } 1086 1087 // ListDouble extracts the leaf list values 1088 func (tv *TypedLeafListDouble) ListDouble() []float64 { 1089 count := len(tv.Bytes) / 8 1090 doubles := make([]float64, 0) 1091 1092 for i := 0; i < count; i++ { 1093 v := tv.Bytes[i*8 : i*8+8] 1094 doubles = append(doubles, float64(math.Float64frombits(binary.LittleEndian.Uint64(v)))) 1095 } 1096 1097 return doubles 1098 } 1099 1100 //////////////////////////////////////////////////////////////////////////////// 1101 // TypedLeafListBytes 1102 //////////////////////////////////////////////////////////////////////////////// 1103 1104 // TypedLeafListBytes for an bool leaf list 1105 type TypedLeafListBytes TypedValue 1106 1107 // NewLeafListBytesTv decodes byte values in to a Leaf list 1108 func NewLeafListBytesTv(values [][]byte) *TypedValue { 1109 return (*TypedValue)(newLeafListBytes(values)) 1110 } 1111 1112 // newLeafListBytes decodes byte values in to a Leaf list type 1113 func newLeafListBytes(values [][]byte) *TypedLeafListBytes { 1114 bytes := make([]byte, 0) 1115 typeopts := make([]int32, 0) 1116 for _, v := range values { 1117 bytes = append(bytes, v...) 1118 typeopts = append(typeopts, int32(len(v))) 1119 } 1120 typedLeafListBytes := TypedLeafListBytes{ 1121 Bytes: bytes, 1122 Type: ValueType_LEAFLIST_BYTES, // Contains the lengths of each byte array in list 1123 TypeOpts: typeopts, 1124 } 1125 return &typedLeafListBytes 1126 } 1127 1128 // ValueType gives the value type 1129 func (tv *TypedLeafListBytes) ValueType() ValueType { 1130 return tv.Type 1131 } 1132 1133 func (tv *TypedLeafListBytes) String() string { 1134 return fmt.Sprintf("%v", tv.List()) 1135 } 1136 1137 // List extracts the leaf list values 1138 func (tv *TypedLeafListBytes) List() [][]byte { 1139 bytes := make([][]byte, 0) 1140 buf := make([]byte, 0) 1141 idx := 0 1142 startAt := 0 1143 for i, b := range tv.Bytes { 1144 valueLen := tv.TypeOpts[idx] 1145 if i-startAt == int(valueLen) { 1146 bytes = append(bytes, buf) 1147 buf = make([]byte, 0) 1148 idx = idx + 1 1149 startAt = startAt + int(valueLen) 1150 } 1151 buf = append(buf, b) 1152 } 1153 bytes = append(bytes, buf) 1154 return bytes 1155 } 1156 1157 func strDecimal64(digits int64, precision uint8) string { 1158 var i, frac int64 1159 if precision > 0 { 1160 div := int64(10) 1161 it := precision - 1 1162 for it > 0 { 1163 div *= 10 1164 it-- 1165 } 1166 i = digits / div 1167 frac = digits % div 1168 } else { 1169 i = digits 1170 } 1171 if frac < 0 { 1172 frac = -frac 1173 } 1174 if precision == 0 { 1175 return fmt.Sprintf("%d", i) 1176 } 1177 fmtString := fmt.Sprintf("%s0.%d%s", "%d.%", precision, "d") 1178 return fmt.Sprintf(fmtString, i, frac) 1179 }