What is your use-case and why do you need this feature?
Use Case: I need to send a CBOR payload to an external device, who's firmware expects certain data to be in the Byte String format.
As I can't modify the firmware to accept an array of bytes as opposed to a byte string, I need this library to support encoding CBOR's Byte String type.
Describe the solution you'd like
As described by the _Major Types_ section in CBOR RFC-7049, CBOR includes a major type specifically for byte strings. In instances where a service or receiver expects a byte string, a user of this library's existing CBOR serialization implementation would be unable to send a byte string as the Cbor class only includes support for the Text, Negative Integer, Array and Map major types.
Ideally, as a user of the library, it would be great to be able to either
Wrap my ByteArray in a type that has its own serializer (could probably be the same as the ByteArraySerializer) and a descriptor that defaults to a CBOR specific SerialKind (BYTE_STRING); or
Use a ByteStringSerializer() to provide to my own custom serializer; or
Create my own serializer within my class and instruct the encoder to explicitly encode a provided ByteArray as a ByteString.
The Cbor class would need to include the byte string header type (0b010_00000) in its Default companion object and update the CborWriter, CborEncoder, CborReader, and CborDecoder to handle that type appropriately.
I tried taking the approach outlined in https://github.com/Kotlin/kotlinx.serialization/pull/846#issuecomment-637760591 (whereas encoding/decoding of ByteArray can be controlled via annotation): https://github.com/Kotlin/kotlinx.serialization/compare/dev...twyatt:CBOR/ByteString
Was able to get encoding working (albeit by holding state of the desired encoding, which felt a bit hacky).
Unfortunately I've hit a wall when attempting decoding:
The current CBOR decoder implementation (CborReader) extends AbstractDecoder:
https://github.com/Kotlin/kotlinx.serialization/blob/626cc01d4c20ad19569a129188153f56df446216/formats/cbor/commonMain/src/kotlinx/serialization/cbor/Cbor.kt#L174
As far as I understand, I need the index in order to use SerialDescriptor.getElementAnnotations (to check for the @ByteString annotation); since AbstractDecoder.decodeSerializableElement is final, there's no way to access the needed index (with the current CborReader design).
A similar (yet hopefully simplified) approach as the technique used with ProtoId could be applied to the CBOR design; whereas a new CBOR reader class is created that does not extend AbstractDecoder and instead implements CompositeDecoder (and delegates as needed). Does this sound like the right approach?
Please advise. Thanks!
I think you can use the same approach that you used in encoding without changing base classes much:
You check for annotation in encodeElement, which has an index, and then handle state in encodeSerializableValue.
For decoding, you can check annotation in the decodeElementIndex at found index before returning it; then, in decodeSerializableValue, you'll have the same state.
Fixed in 1.0.0-RC2
Most helpful comment
Fixed in 1.0.0-RC2