xref: /aosp_15_r20/external/kotlinx.serialization/core/commonMain/src/kotlinx/serialization/SerialFormat.kt (revision 57b5a4a64c534cf7f27ac9427ceab07f3d8ed3d8)
1 /*
2  * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.serialization
6 
7 import kotlinx.serialization.internal.*
8 import kotlinx.serialization.encoding.*
9 import kotlinx.serialization.modules.*
10 
11 /**
12  * Represents an instance of a serialization format
13  * that can interact with [KSerializer] and is a supertype of all entry points for a serialization.
14  * It does not impose any restrictions on a serialized form or underlying storage, neither it exposes them.
15  *
16  * Concrete data types and API for user-interaction are responsibility of a concrete subclass or subinterface,
17  * for example [StringFormat], [BinaryFormat] or `Json`.
18  *
19  * Typically, formats have their specific [Encoder] and [Decoder] implementations
20  * as private classes and do not expose them.
21  *
22  * ### Exception types for `SerialFormat` implementation
23  *
24  * Methods responsible for format-specific encoding and decoding are allowed to throw
25  * any subtype of [IllegalArgumentException] in order to indicate serialization
26  * and deserialization errors. It is recommended to throw subtypes of [SerializationException]
27  * for encoder and decoder specific errors and [IllegalArgumentException] for input
28  * and output validation-specific errors.
29  *
30  * For formats
31  *
32  * ### Not stable for inheritance
33  *
34  * `SerialFormat` interface is not stable for inheritance in 3rd party libraries, as new methods
35  * might be added to this interface or contracts of the existing methods can be changed.
36  *
37  * It is safe to operate with instances of `SerialFormat` and call its methods.
38  */
39 public interface SerialFormat {
40     /**
41      * Contains all serializers registered by format user for [Contextual] and [Polymorphic] serialization.
42      *
43      * The same module should be exposed in the format's [Encoder] and [Decoder].
44      */
45     public val serializersModule: SerializersModule
46 }
47 
48 /**
49  * [SerialFormat] that allows conversions to and from [ByteArray] via [encodeToByteArray] and [decodeFromByteArray] methods.
50  *
51  * ### Not stable for inheritance
52  *
53  * `BinaryFormat` interface is not stable for inheritance in 3rd party libraries, as new methods
54  * might be added to this interface or contracts of the existing methods can be changed.
55  *
56  * It is safe to operate with instances of `BinaryFormat` and call its methods.
57  */
58 public interface BinaryFormat : SerialFormat {
59 
60     /**
61      * Serializes and encodes the given [value] to byte array using the given [serializer].
62      *
63      * @throws SerializationException in case of any encoding-specific error
64      * @throws IllegalArgumentException if the encoded input does not comply format's specification
65      */
encodeToByteArraynull66     public fun <T> encodeToByteArray(serializer: SerializationStrategy<T>, value: T): ByteArray
67 
68     /**
69      * Decodes and deserializes the given [byte array][bytes] to the value of type [T] using the given [deserializer].
70      *
71      * @throws SerializationException in case of any decoding-specific error
72      * @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
73      */
74     public fun <T> decodeFromByteArray(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T
75 }
76 
77 /**
78  * [SerialFormat] that allows conversions to and from [String] via [encodeToString] and [decodeFromString] methods.
79  *
80  * ### Not stable for inheritance
81  *
82  * `StringFormat` interface is not stable for inheritance in 3rd party libraries, as new methods
83  * might be added to this interface or contracts of the existing methods can be changed.
84  *
85  * It is safe to operate with instances of `StringFormat` and call its methods.
86  */
87 public interface StringFormat : SerialFormat {
88 
89     /**
90      * Serializes and encodes the given [value] to string using the given [serializer].
91      *
92      * @throws SerializationException in case of any encoding-specific error
93      * @throws IllegalArgumentException if the encoded input does not comply format's specification
94      */
95     public fun <T> encodeToString(serializer: SerializationStrategy<T>, value: T): String
96 
97     /**
98      * Decodes and deserializes the given [string] to the value of type [T] using the given [deserializer].
99      *
100      * @throws SerializationException in case of any decoding-specific error
101      * @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
102      */
103     public fun <T> decodeFromString(deserializer: DeserializationStrategy<T>, string: String): T
104 }
105 
106 /**
107  * Serializes and encodes the given [value] to string using serializer retrieved from the reified type parameter.
108  *
109  * @throws SerializationException in case of any encoding-specific error
110  * @throws IllegalArgumentException if the encoded input does not comply format's specification
111  */
encodeToStringnull112 public inline fun <reified T> StringFormat.encodeToString(value: T): String =
113     encodeToString(serializersModule.serializer(), value)
114 
115 /**
116  * Decodes and deserializes the given [string] to the value of type [T] using deserializer
117  * retrieved from the reified type parameter.
118  *
119  * @throws SerializationException in case of any decoding-specific error
120  * @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
121  */
122 public inline fun <reified T> StringFormat.decodeFromString(string: String): T =
123     decodeFromString(serializersModule.serializer(), string)
124 
125 
126 /**
127  * Serializes and encodes the given [value] to byte array, delegating it to the [BinaryFormat],
128  * and then encodes resulting bytes to hex string.
129  *
130  * Hex representation does not interfere with serialization and encoding process of the format and
131  * only applies transformation to the resulting array. It is recommended to use for debugging and
132  * testing purposes.
133  *
134  * @throws SerializationException in case of any encoding-specific error
135  * @throws IllegalArgumentException if the encoded input does not comply format's specification
136  */
137 public fun <T> BinaryFormat.encodeToHexString(serializer: SerializationStrategy<T>, value: T): String =
138     InternalHexConverter.printHexBinary(encodeToByteArray(serializer, value), lowerCase = true)
139 
140 /**
141  * Decodes byte array from the given [hex] string and the decodes and deserializes it
142  * to the value of type [T], delegating it to the [BinaryFormat].
143  *
144  * This method is a counterpart to [encodeToHexString].
145  *
146  * @throws SerializationException in case of any decoding-specific error
147  * @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
148  */
149 public fun <T> BinaryFormat.decodeFromHexString(deserializer: DeserializationStrategy<T>, hex: String): T =
150     decodeFromByteArray(deserializer, InternalHexConverter.parseHexBinary(hex))
151 
152 /**
153  * Serializes and encodes the given [value] to byte array, delegating it to the [BinaryFormat],
154  * and then encodes resulting bytes to hex string.
155  *
156  * Hex representation does not interfere with serialization and encoding process of the format and
157  * only applies transformation to the resulting array. It is recommended to use for debugging and
158  * testing purposes.
159  *
160  * @throws SerializationException in case of any encoding-specific error
161  * @throws IllegalArgumentException if the encoded input does not comply format's specification
162  */
163 public inline fun <reified T> BinaryFormat.encodeToHexString(value: T): String =
164     encodeToHexString(serializersModule.serializer(), value)
165 
166 /**
167  * Decodes byte array from the given [hex] string and the decodes and deserializes it
168  * to the value of type [T], delegating it to the [BinaryFormat].
169  *
170  * This method is a counterpart to [encodeToHexString].
171  *
172  * @throws SerializationException in case of any decoding-specific error
173  * @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
174  */
175 public inline fun <reified T> BinaryFormat.decodeFromHexString(hex: String): T =
176     decodeFromHexString(serializersModule.serializer(), hex)
177 
178 /**
179  * Serializes and encodes the given [value] to byte array using serializer
180  * retrieved from the reified type parameter.
181  *
182  * @throws SerializationException in case of any encoding-specific error
183  * @throws IllegalArgumentException if the encoded input does not comply format's specification
184  */
185 public inline fun <reified T> BinaryFormat.encodeToByteArray(value: T): ByteArray =
186     encodeToByteArray(serializersModule.serializer(), value)
187 
188 /**
189  * Decodes and deserializes the given [byte array][bytes] to the value of type [T] using deserializer
190  * retrieved from the reified type parameter.
191  *
192  * @throws SerializationException in case of any decoding-specific error
193  * @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
194  */
195 public inline fun <reified T> BinaryFormat.decodeFromByteArray(bytes: ByteArray): T =
196     decodeFromByteArray(serializersModule.serializer(), bytes)
197