@@ -26,10 +26,9 @@ private fun Stack.peek() = last()
26
26
// Split implementation to optimize base case
27
27
internal sealed class CborWriter (
28
28
override val cbor : Cbor ,
29
- protected val output : ByteArrayOutput ,
30
29
) : AbstractEncoder(), CborEncoder {
31
30
32
- internal fun encodeByteString (byteArray : ByteArray ) {
31
+ internal open fun encodeByteString (byteArray : ByteArray ) {
33
32
getDestination().encodeByteString(byteArray)
34
33
}
35
34
@@ -155,8 +154,8 @@ internal sealed class CborWriter(
155
154
156
155
157
156
// optimized indefinite length encoder
158
- internal class IndefiniteLengthCborWriter (cbor : Cbor , output : ByteArrayOutput ) : CborWriter(
159
- cbor, output
157
+ internal class IndefiniteLengthCborWriter (cbor : Cbor , private val output : ByteArrayOutput ) : CborWriter(
158
+ cbor
160
159
) {
161
160
162
161
override fun beginStructure (descriptor : SerialDescriptor ): CompositeEncoder {
@@ -187,8 +186,162 @@ internal class IndefiniteLengthCborWriter(cbor: Cbor, output: ByteArrayOutput) :
187
186
188
187
}
189
188
189
+ // optimized indefinite length encoder
190
+ internal class StructuredCborWriter (cbor : Cbor ) : CborWriter(
191
+ cbor
192
+ ) {
193
+
194
+ sealed class CborContainer (tags : ULongArray , elements : MutableList <CborElement >) {
195
+ var elements = elements
196
+ private set
197
+
198
+ var tags = tags
199
+ internal set
200
+
201
+
202
+ fun add (element : CborElement ) = elements.add(element)
203
+ class Map (tags : ULongArray , elements : MutableList <CborElement > = mutableListOf()) :
204
+ CborContainer (tags, elements) {
205
+ }
206
+
207
+ class List (tags : ULongArray , elements : MutableList <CborElement > = mutableListOf()) :
208
+ CborContainer (tags, elements) {
209
+ }
210
+
211
+ class Primitive (tags : ULongArray ) : CborContainer(tags, elements = mutableListOf()) {
212
+
213
+ }
214
+
215
+ fun finalize () = when (this ) {
216
+ is List -> CborList (content = elements, tags = tags)
217
+ is Map -> CborMap (
218
+ content = if (elements.isNotEmpty()) IntRange (0 , elements.size / 2 - 1 ).associate {
219
+ elements[it * 2 ] to elements[it * 2 + 1 ]
220
+ } else mapOf (),
221
+ tags = tags
222
+ )
223
+
224
+ is Primitive -> elements.first().also { it.tags = tags }
225
+
226
+ }
227
+ }
228
+
229
+ private val stack = ArrayDeque <CborContainer >()
230
+ private var currentElement: CborContainer ? = null
231
+
232
+ fun finalize () = currentElement!! .finalize()
233
+
234
+ override fun beginStructure (descriptor : SerialDescriptor ): CompositeEncoder {
235
+ val tags = descriptor.getObjectTags() ? : ulongArrayOf()
236
+ val element = if (descriptor.hasArrayTag()) {
237
+ CborContainer .List (tags)
238
+ } else {
239
+ when (descriptor.kind) {
240
+ StructureKind .LIST , is PolymorphicKind -> CborContainer .List (tags)
241
+ is StructureKind .MAP -> CborContainer .Map (tags)
242
+ else -> CborContainer .Map (tags)
243
+ }
244
+ }
245
+ currentElement?.let { stack.add(it) }
246
+ currentElement = element
247
+ return this
248
+ }
249
+
250
+ override fun endStructure (descriptor : SerialDescriptor ) {
251
+ val finalized = currentElement!! .finalize()
252
+ if (stack.isNotEmpty()) {
253
+ currentElement = stack.removeLast()
254
+ currentElement!! .add(finalized)
255
+ }
256
+ }
257
+
258
+ override fun getDestination () = TODO ()
259
+
260
+
261
+ override fun incrementChildren () {/* NOOP*/
262
+ }
263
+
264
+
265
+ override fun encodeElement (descriptor : SerialDescriptor , index : Int ): Boolean {
266
+ // TODO check if cborelement and be done
267
+ val name = descriptor.getElementName(index)
268
+ if (! descriptor.hasArrayTag()) {
269
+ val keyTags = descriptor.getKeyTags(index)
270
+
271
+ if ((descriptor.kind !is StructureKind .LIST ) && (descriptor.kind !is StructureKind .MAP ) && (descriptor.kind !is PolymorphicKind )) {
272
+ // indices are put into the name field. we don't want to write those, as it would result in double writes
273
+ val cborLabel = descriptor.getCborLabel(index)
274
+ if (cbor.configuration.preferCborLabelsOverNames && cborLabel != null ) {
275
+ currentElement!! .add(
276
+ CborInt (cborLabel, keyTags ? : ulongArrayOf())
277
+ )
278
+ } else {
279
+ currentElement!! .add(CborString (name, keyTags ? : ulongArrayOf()))
280
+ }
281
+ }
282
+ }
283
+
284
+ if (cbor.configuration.encodeValueTags) {
285
+ descriptor.getValueTags(index)?.let { valueTags ->
286
+ currentElement!! .tags + = valueTags
287
+ }
288
+ }
289
+ return true
290
+ }
291
+
292
+
293
+ override fun encodeBoolean (value : Boolean ) {
294
+ currentElement!! .add(CborBoolean (value))
295
+ }
296
+
297
+ override fun encodeByte (value : Byte ) {
298
+ currentElement!! .add(CborInt (value.toLong()))
299
+ }
300
+
301
+ override fun encodeChar (value : Char ) {
302
+ currentElement!! .add(CborInt (value.code.toLong()))
303
+ }
304
+
305
+ override fun encodeDouble (value : Double ) {
306
+ currentElement!! .add(CborDouble (value))
307
+ }
308
+
309
+ override fun encodeFloat (value : Float ) {
310
+ currentElement!! .add(CborDouble (value.toDouble()))
311
+ }
312
+
313
+ override fun encodeInt (value : Int ) {
314
+ currentElement!! .add(CborInt (value.toLong()))
315
+ }
316
+
317
+ override fun encodeLong (value : Long ) {
318
+ currentElement!! .add(CborInt (value))
319
+ }
320
+
321
+ override fun encodeShort (value : Short ) {
322
+ currentElement!! .add(CborInt (value.toLong()))
323
+ }
324
+
325
+ override fun encodeString (value : String ) {
326
+ currentElement!! .add(CborString (value))
327
+ }
328
+
329
+ override fun encodeByteString (byteArray : ByteArray ) {
330
+ currentElement!! .add(CborByteString (byteArray))
331
+ }
332
+
333
+ override fun encodeNull () {
334
+ currentElement!! .add(CborNull ())
335
+ }
336
+
337
+ override fun encodeEnum (enumDescriptor : SerialDescriptor , index : Int ) {
338
+ currentElement!! .add(CborString (enumDescriptor.getElementName(index)))
339
+ }
340
+
341
+ }
342
+
190
343
// optimized definite length encoder
191
- internal class DefiniteLengthCborWriter (cbor : Cbor , output : ByteArrayOutput ) : CborWriter(cbor, output ) {
344
+ internal class DefiniteLengthCborWriter (cbor : Cbor , output : ByteArrayOutput ) : CborWriter(cbor) {
192
345
193
346
private val structureStack = Stack (Data (output, - 1 ))
194
347
override fun getDestination (): ByteArrayOutput =
0 commit comments