/* * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.serialization import kotlinx.serialization.internal.* import kotlinx.serialization.encoding.* import kotlinx.serialization.modules.* /** * Represents an instance of a serialization format * that can interact with [KSerializer] and is a supertype of all entry points for a serialization. * It does not impose any restrictions on a serialized form or underlying storage, neither it exposes them. * * Concrete data types and API for user-interaction are responsibility of a concrete subclass or subinterface, * for example [StringFormat], [BinaryFormat] or `Json`. * * Typically, formats have their specific [Encoder] and [Decoder] implementations * as private classes and do not expose them. * * ### Exception types for `SerialFormat` implementation * * Methods responsible for format-specific encoding and decoding are allowed to throw * any subtype of [IllegalArgumentException] in order to indicate serialization * and deserialization errors. It is recommended to throw subtypes of [SerializationException] * for encoder and decoder specific errors and [IllegalArgumentException] for input * and output validation-specific errors. * * For formats * * ### Not stable for inheritance * * `SerialFormat` interface is not stable for inheritance in 3rd party libraries, as new methods * might be added to this interface or contracts of the existing methods can be changed. * * It is safe to operate with instances of `SerialFormat` and call its methods. */ public interface SerialFormat { /** * Contains all serializers registered by format user for [Contextual] and [Polymorphic] serialization. * * The same module should be exposed in the format's [Encoder] and [Decoder]. */ public val serializersModule: SerializersModule } /** * [SerialFormat] that allows conversions to and from [ByteArray] via [encodeToByteArray] and [decodeFromByteArray] methods. * * ### Not stable for inheritance * * `BinaryFormat` interface is not stable for inheritance in 3rd party libraries, as new methods * might be added to this interface or contracts of the existing methods can be changed. * * It is safe to operate with instances of `BinaryFormat` and call its methods. */ public interface BinaryFormat : SerialFormat { /** * Serializes and encodes the given [value] to byte array using the given [serializer]. * * @throws SerializationException in case of any encoding-specific error * @throws IllegalArgumentException if the encoded input does not comply format's specification */ public fun encodeToByteArray(serializer: SerializationStrategy, value: T): ByteArray /** * Decodes and deserializes the given [byte array][bytes] to the value of type [T] using the given [deserializer]. * * @throws SerializationException in case of any decoding-specific error * @throws IllegalArgumentException if the decoded input is not a valid instance of [T] */ public fun decodeFromByteArray(deserializer: DeserializationStrategy, bytes: ByteArray): T } /** * [SerialFormat] that allows conversions to and from [String] via [encodeToString] and [decodeFromString] methods. * * ### Not stable for inheritance * * `StringFormat` interface is not stable for inheritance in 3rd party libraries, as new methods * might be added to this interface or contracts of the existing methods can be changed. * * It is safe to operate with instances of `StringFormat` and call its methods. */ public interface StringFormat : SerialFormat { /** * Serializes and encodes the given [value] to string using the given [serializer]. * * @throws SerializationException in case of any encoding-specific error * @throws IllegalArgumentException if the encoded input does not comply format's specification */ public fun encodeToString(serializer: SerializationStrategy, value: T): String /** * Decodes and deserializes the given [string] to the value of type [T] using the given [deserializer]. * * @throws SerializationException in case of any decoding-specific error * @throws IllegalArgumentException if the decoded input is not a valid instance of [T] */ public fun decodeFromString(deserializer: DeserializationStrategy, string: String): T } /** * Serializes and encodes the given [value] to string using serializer retrieved from the reified type parameter. * * @throws SerializationException in case of any encoding-specific error * @throws IllegalArgumentException if the encoded input does not comply format's specification */ public inline fun StringFormat.encodeToString(value: T): String = encodeToString(serializersModule.serializer(), value) /** * Decodes and deserializes the given [string] to the value of type [T] using deserializer * retrieved from the reified type parameter. * * @throws SerializationException in case of any decoding-specific error * @throws IllegalArgumentException if the decoded input is not a valid instance of [T] */ public inline fun StringFormat.decodeFromString(string: String): T = decodeFromString(serializersModule.serializer(), string) /** * Serializes and encodes the given [value] to byte array, delegating it to the [BinaryFormat], * and then encodes resulting bytes to hex string. * * Hex representation does not interfere with serialization and encoding process of the format and * only applies transformation to the resulting array. It is recommended to use for debugging and * testing purposes. * * @throws SerializationException in case of any encoding-specific error * @throws IllegalArgumentException if the encoded input does not comply format's specification */ public fun BinaryFormat.encodeToHexString(serializer: SerializationStrategy, value: T): String = InternalHexConverter.printHexBinary(encodeToByteArray(serializer, value), lowerCase = true) /** * Decodes byte array from the given [hex] string and the decodes and deserializes it * to the value of type [T], delegating it to the [BinaryFormat]. * * This method is a counterpart to [encodeToHexString]. * * @throws SerializationException in case of any decoding-specific error * @throws IllegalArgumentException if the decoded input is not a valid instance of [T] */ public fun BinaryFormat.decodeFromHexString(deserializer: DeserializationStrategy, hex: String): T = decodeFromByteArray(deserializer, InternalHexConverter.parseHexBinary(hex)) /** * Serializes and encodes the given [value] to byte array, delegating it to the [BinaryFormat], * and then encodes resulting bytes to hex string. * * Hex representation does not interfere with serialization and encoding process of the format and * only applies transformation to the resulting array. It is recommended to use for debugging and * testing purposes. * * @throws SerializationException in case of any encoding-specific error * @throws IllegalArgumentException if the encoded input does not comply format's specification */ public inline fun BinaryFormat.encodeToHexString(value: T): String = encodeToHexString(serializersModule.serializer(), value) /** * Decodes byte array from the given [hex] string and the decodes and deserializes it * to the value of type [T], delegating it to the [BinaryFormat]. * * This method is a counterpart to [encodeToHexString]. * * @throws SerializationException in case of any decoding-specific error * @throws IllegalArgumentException if the decoded input is not a valid instance of [T] */ public inline fun BinaryFormat.decodeFromHexString(hex: String): T = decodeFromHexString(serializersModule.serializer(), hex) /** * Serializes and encodes the given [value] to byte array using serializer * retrieved from the reified type parameter. * * @throws SerializationException in case of any encoding-specific error * @throws IllegalArgumentException if the encoded input does not comply format's specification */ public inline fun BinaryFormat.encodeToByteArray(value: T): ByteArray = encodeToByteArray(serializersModule.serializer(), value) /** * Decodes and deserializes the given [byte array][bytes] to the value of type [T] using deserializer * retrieved from the reified type parameter. * * @throws SerializationException in case of any decoding-specific error * @throws IllegalArgumentException if the decoded input is not a valid instance of [T] */ public inline fun BinaryFormat.decodeFromByteArray(bytes: ByteArray): T = decodeFromByteArray(serializersModule.serializer(), bytes)