package cbor import ( "errors" "fmt" "reflect" ) // SimpleValue represents CBOR simple value. // CBOR simple value is: // - an extension point like CBOR tag. // - a subset of CBOR major type 7 that isn't floating-point. // - "identified by a number between 0 and 255, but distinct from that number itself". // For example, "a simple value 2 is not equivalent to an integer 2" as a CBOR map key. // // CBOR simple values identified by 20..23 are: "false", "true" , "null", and "undefined". // Other CBOR simple values are currently unassigned/reserved by IANA. type SimpleValue uint8 var ( typeSimpleValue = reflect.TypeOf(SimpleValue(0)) ) // MarshalCBOR encodes SimpleValue as CBOR simple value (major type 7). func (sv SimpleValue) MarshalCBOR() ([]byte, error) { // RFC 8949 3.3. Floating-Point Numbers and Values with No Content says: // "An encoder MUST NOT issue two-byte sequences that start with 0xf8 // (major type 7, additional information 24) and continue with a byte // less than 0x20 (32 decimal). Such sequences are not well-formed. // (This implies that an encoder cannot encode false, true, null, or // undefined in two-byte sequences and that only the one-byte variants // of these are well-formed; more generally speaking, each simple value // only has a single representation variant)." switch { case sv <= maxSimpleValueInAdditionalInformation: return []byte{byte(cborTypePrimitives) | byte(sv)}, nil case sv >= minSimpleValueIn1ByteArgument: return []byte{byte(cborTypePrimitives) | additionalInformationWith1ByteArgument, byte(sv)}, nil default: return nil, &UnsupportedValueError{msg: fmt.Sprintf("SimpleValue(%d)", sv)} } } // UnmarshalCBOR decodes CBOR simple value (major type 7) to SimpleValue. func (sv *SimpleValue) UnmarshalCBOR(data []byte) error { if sv == nil { return errors.New("cbor.SimpleValue: UnmarshalCBOR on nil pointer") } d := decoder{data: data, dm: defaultDecMode} typ, ai, val := d.getHead() if typ != cborTypePrimitives { return &UnmarshalTypeError{CBORType: typ.String(), GoType: "SimpleValue"} } if ai > additionalInformationWith1ByteArgument { return &UnmarshalTypeError{CBORType: typ.String(), GoType: "SimpleValue", errorMsg: "not simple values"} } // It is safe to cast val to uint8 here because // - data is already verified to be well-formed CBOR simple value and // - val is <= math.MaxUint8. *sv = SimpleValue(val) return nil }