2025-01-18 04:28:11 +03:00

107 lines
3.8 KiB
Kotlin

package net.sergeych.bipack
import kotlinx.serialization.SerialInfo
/**
* To be used with [kotlinx.serialization.Serializable]. Allows serialized classes to be
* extended by _adding members with default initializers_ __to the end of the constructor list__.
*
* This annotation makes Bipack to insert fields count before the
* serialized data. It then checks it on deserializing to fill not serialized fields will
* default values.
*
* Note that since 0.0.7 the same behavior could be achieved by serializing each instance in the
* array as Bipack correctly processes end-of-data by filling missing fields with default values,
* using `Extendable` is more convenient and save some space, most of the time.
*
* _Please note that without this annotation it could be impossible to deserialize old versions of
* the class, in particular, in array, inner fields, etc._
*/
@Target(AnnotationTarget.CLASS)
@SerialInfo
annotation class Extendable
/**
* Serializable classes annotated as Framed will have leading checked mark as CRC32
* of its name (uses `@SerialName` internally). On deserializing, if frame will not
* match the expected name, the [InvalidFrameException] will be thrown.
*/
@SerialInfo
annotation class Framed
/**
* Allow to CRC-protect structures (we suppose to use it with classes only). After the
* data block its CRC32 will be written and checked. It is memory-wise: it calculates CRC
* on the fly without buffering the data. If used with [Framed] and [Extendable] the extra
* data is protected too.
*
* __Common pitfalls__. When unpacking corrupted data protected this way, the not only [InvalidFrameCRCException]
* can be thrown. Actually, most often you will see [DataSource.EndOfData] exception
*/
@SerialInfo
annotation class CrcProtected
/**
* Allow marking data fields as being serialized as unsigned (applicable also to signed fields lite Int, Long and
* Short, if you are sure they will not be negative). As unsigned types are not cully supported by `kotlinx.serialization`
* it is the only way to tell the serialized to use more compact unsigned variable length encoding.
*/
@SerialInfo
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class Unsigned
/**
* Fixed size collection of a given size. __Use it only with collections!__
*
* Use it with collection of fixed size, to read/write exact number of items (for example, bytes),
* like hash digest, key bits and so on. Does not store/load the collection
* size what reduces packed size to at least one byte. depending on the actual
* collection size. As for nowonly collection types (e.g. ByteArray, List<T>m etc) are supported.
* Note that if the actual collection size differs from [size], [BipackEncoder] will throw
* [WrongCollectionSize] while encoding it. For example:
*
* ~~~
* @Serializable
* class Foo(
* @FixedSize(32)
* thirtyTwoBytes: ByteArray
* )
*/
@SerialInfo
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class FixedSize(val size: Int)
/**
* Fixed-size number, big-endian. Could be used only with field of following types:
*
* - Int, UInt: 4 bytes
* - Short, UShort: 2 bytes
* - Long, ULong: 8 bytes.
*
* It should not be used with Byte or UByte as their size is always 1 byte ;)
*
* Example:
* ~~~
* @Serializable
* class Foo(
* @Fixed
* val eightBytesLongInt: Long
* )
*
* // so:
* assertEquals("00 00 00 01 00 00 00 02", BipackEncoder.encode(Foo(0x100000002)).encodeToHex())
* ~~~
*/
@SerialInfo
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class Fixed
open class InvalidFrameException(reason: String) : Exception(reason)
class InvalidFrameHeaderException(reason: String = "Frame header does not match") : InvalidFrameException(reason)
class InvalidFrameCRCException : InvalidFrameException("Checksum CRC32 failed")
class WrongCollectionSize(reason: String) : Exception(reason)