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