xref: /aosp_15_r20/external/kotlinx.serialization/guide/example/example-formats-16.kt (revision 57b5a4a64c534cf7f27ac9427ceab07f3d8ed3d8)
1 // This file was automatically generated from formats.md by Knit tool. Do not edit.
2 package example.exampleFormats16
3 
4 import kotlinx.serialization.*
5 import kotlinx.serialization.Serializable
6 import kotlinx.serialization.descriptors.*
7 import kotlinx.serialization.modules.*
8 import kotlinx.serialization.encoding.*
9 import java.io.*
10 
11 private val byteArraySerializer = serializer<ByteArray>()
12 class DataOutputEncoder(val output: DataOutput) : AbstractEncoder() {
13     override val serializersModule: SerializersModule = EmptySerializersModule()
encodeBooleannull14     override fun encodeBoolean(value: Boolean) = output.writeByte(if (value) 1 else 0)
15     override fun encodeByte(value: Byte) = output.writeByte(value.toInt())
16     override fun encodeShort(value: Short) = output.writeShort(value.toInt())
17     override fun encodeInt(value: Int) = output.writeInt(value)
18     override fun encodeLong(value: Long) = output.writeLong(value)
19     override fun encodeFloat(value: Float) = output.writeFloat(value)
20     override fun encodeDouble(value: Double) = output.writeDouble(value)
21     override fun encodeChar(value: Char) = output.writeChar(value.code)
22     override fun encodeString(value: String) = output.writeUTF(value)
23     override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) = output.writeInt(index)
24 
25     override fun beginCollection(descriptor: SerialDescriptor, collectionSize: Int): CompositeEncoder {
26         encodeInt(collectionSize)
27         return this
28     }
29 
encodeNullnull30     override fun encodeNull() = encodeBoolean(false)
31     override fun encodeNotNullMark() = encodeBoolean(true)
32 
33     override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
34         if (serializer.descriptor == byteArraySerializer.descriptor)
35             encodeByteArray(value as ByteArray)
36         else
37             super.encodeSerializableValue(serializer, value)
38     }
39 
encodeByteArraynull40     private fun encodeByteArray(bytes: ByteArray) {
41         encodeCompactSize(bytes.size)
42         output.write(bytes)
43     }
44 
encodeCompactSizenull45     private fun encodeCompactSize(value: Int) {
46         if (value < 0xff) {
47             output.writeByte(value)
48         } else {
49             output.writeByte(0xff)
50             output.writeInt(value)
51         }
52     }
53 }
54 
encodeTonull55 fun <T> encodeTo(output: DataOutput, serializer: SerializationStrategy<T>, value: T) {
56     val encoder = DataOutputEncoder(output)
57     encoder.encodeSerializableValue(serializer, value)
58 }
59 
encodeTonull60 inline fun <reified T> encodeTo(output: DataOutput, value: T) = encodeTo(output, serializer(), value)
61 
62 class DataInputDecoder(val input: DataInput, var elementsCount: Int = 0) : AbstractDecoder() {
63     private var elementIndex = 0
64     override val serializersModule: SerializersModule = EmptySerializersModule()
65     override fun decodeBoolean(): Boolean = input.readByte().toInt() != 0
66     override fun decodeByte(): Byte = input.readByte()
67     override fun decodeShort(): Short = input.readShort()
68     override fun decodeInt(): Int = input.readInt()
69     override fun decodeLong(): Long = input.readLong()
70     override fun decodeFloat(): Float = input.readFloat()
71     override fun decodeDouble(): Double = input.readDouble()
72     override fun decodeChar(): Char = input.readChar()
73     override fun decodeString(): String = input.readUTF()
74     override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = input.readInt()
75 
76     override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
77         if (elementIndex == elementsCount) return CompositeDecoder.DECODE_DONE
78         return elementIndex++
79     }
80 
81     override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder =
82         DataInputDecoder(input, descriptor.elementsCount)
83 
84     override fun decodeSequentially(): Boolean = true
85 
86     override fun decodeCollectionSize(descriptor: SerialDescriptor): Int =
87         decodeInt().also { elementsCount = it }
88 
89     override fun decodeNotNullMark(): Boolean = decodeBoolean()
90 
91     @Suppress("UNCHECKED_CAST")
92     override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>, previousValue: T?): T =
93         if (deserializer.descriptor == byteArraySerializer.descriptor)
94             decodeByteArray() as T
95         else
96             super.decodeSerializableValue(deserializer, previousValue)
97 
98     private fun decodeByteArray(): ByteArray {
99         val bytes = ByteArray(decodeCompactSize())
100         input.readFully(bytes)
101         return bytes
102     }
103 
104     private fun decodeCompactSize(): Int {
105         val byte = input.readByte().toInt() and 0xff
106         if (byte < 0xff) return byte
107         return input.readInt()
108     }
109 }
110 
decodeFromnull111 fun <T> decodeFrom(input: DataInput, deserializer: DeserializationStrategy<T>): T {
112     val decoder = DataInputDecoder(input)
113     return decoder.decodeSerializableValue(deserializer)
114 }
115 
decodeFromnull116 inline fun <reified T> decodeFrom(input: DataInput): T = decodeFrom(input, serializer())
117 
118 fun ByteArray.toAsciiHexString() = joinToString("") {
119     if (it in 32..127) it.toInt().toChar().toString() else
120         "{${it.toUByte().toString(16).padStart(2, '0').uppercase()}}"
121 }
122 
123 @Serializable
124 data class Project(val name: String, val attachment: ByteArray)
125 
mainnull126 fun main() {
127     val data = Project("kotlinx.serialization", byteArrayOf(0x0A, 0x0B, 0x0C, 0x0D))
128     val output = ByteArrayOutputStream()
129     encodeTo(DataOutputStream(output), data)
130     val bytes = output.toByteArray()
131     println(bytes.toAsciiHexString())
132     val input = ByteArrayInputStream(bytes)
133     val obj = decodeFrom<Project>(DataInputStream(input))
134     println(obj)
135 }
136