simplevalue.go 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright (c) Faye Amacker. All rights reserved.
  2. // Licensed under the MIT License. See LICENSE in the project root for license information.
  3. package cbor
  4. import (
  5. "errors"
  6. "fmt"
  7. "reflect"
  8. )
  9. // SimpleValue represents CBOR simple value.
  10. // CBOR simple value is:
  11. // - an extension point like CBOR tag.
  12. // - a subset of CBOR major type 7 that isn't floating-point.
  13. // - "identified by a number between 0 and 255, but distinct from that number itself".
  14. // For example, "a simple value 2 is not equivalent to an integer 2" as a CBOR map key.
  15. //
  16. // CBOR simple values identified by 20..23 are: "false", "true" , "null", and "undefined".
  17. // Other CBOR simple values are currently unassigned/reserved by IANA.
  18. type SimpleValue uint8
  19. var (
  20. typeSimpleValue = reflect.TypeOf(SimpleValue(0))
  21. )
  22. // MarshalCBOR encodes SimpleValue as CBOR simple value (major type 7).
  23. func (sv SimpleValue) MarshalCBOR() ([]byte, error) {
  24. // RFC 8949 3.3. Floating-Point Numbers and Values with No Content says:
  25. // "An encoder MUST NOT issue two-byte sequences that start with 0xf8
  26. // (major type 7, additional information 24) and continue with a byte
  27. // less than 0x20 (32 decimal). Such sequences are not well-formed.
  28. // (This implies that an encoder cannot encode false, true, null, or
  29. // undefined in two-byte sequences and that only the one-byte variants
  30. // of these are well-formed; more generally speaking, each simple value
  31. // only has a single representation variant)."
  32. switch {
  33. case sv <= maxSimpleValueInAdditionalInformation:
  34. return []byte{byte(cborTypePrimitives) | byte(sv)}, nil
  35. case sv >= minSimpleValueIn1ByteArgument:
  36. return []byte{byte(cborTypePrimitives) | additionalInformationWith1ByteArgument, byte(sv)}, nil
  37. default:
  38. return nil, &UnsupportedValueError{msg: fmt.Sprintf("SimpleValue(%d)", sv)}
  39. }
  40. }
  41. // UnmarshalCBOR decodes CBOR simple value (major type 7) to SimpleValue.
  42. //
  43. // Deprecated: No longer used by this codec; kept for compatibility
  44. // with user apps that directly call this function.
  45. func (sv *SimpleValue) UnmarshalCBOR(data []byte) error {
  46. if sv == nil {
  47. return errors.New("cbor.SimpleValue: UnmarshalCBOR on nil pointer")
  48. }
  49. d := decoder{data: data, dm: defaultDecMode}
  50. // Check well-formedness of CBOR data item.
  51. // SimpleValue.UnmarshalCBOR() is exported, so
  52. // the codec needs to support same behavior for:
  53. // - Unmarshal(data, *SimpleValue)
  54. // - SimpleValue.UnmarshalCBOR(data)
  55. err := d.wellformed(false, false)
  56. if err != nil {
  57. return err
  58. }
  59. return sv.unmarshalCBOR(data)
  60. }
  61. // unmarshalCBOR decodes CBOR simple value (major type 7) to SimpleValue.
  62. // This function assumes data is well-formed, and does not perform bounds checking.
  63. // This function is called by Unmarshal().
  64. func (sv *SimpleValue) unmarshalCBOR(data []byte) error {
  65. if sv == nil {
  66. return errors.New("cbor.SimpleValue: UnmarshalCBOR on nil pointer")
  67. }
  68. d := decoder{data: data, dm: defaultDecMode}
  69. typ, ai, val := d.getHead()
  70. if typ != cborTypePrimitives {
  71. return &UnmarshalTypeError{CBORType: typ.String(), GoType: "SimpleValue"}
  72. }
  73. if ai > additionalInformationWith1ByteArgument {
  74. return &UnmarshalTypeError{CBORType: typ.String(), GoType: "SimpleValue", errorMsg: "not simple values"}
  75. }
  76. // It is safe to cast val to uint8 here because
  77. // - data is already verified to be well-formed CBOR simple value and
  78. // - val is <= math.MaxUint8.
  79. *sv = SimpleValue(val)
  80. return nil
  81. }