commonMain.com.divpundir.mavlink.serialization.DeserializationUtil.kt Maven / Gradle / Ivy
package com.divpundir.mavlink.serialization
/**
* Reads a [Byte]/Int8 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt8(): Byte =
safeDecodePrimitive(Byte.SIZE_BYTES, 0, MavDataDecoder::decodeByte)
/**
* Reads a [UByte]/UInt8 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt8(): UByte =
safeDecodePrimitive(UByte.SIZE_BYTES, 0u, MavDataDecoder::decodeUByte)
/**
* Reads a [Short]/Int16 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt16(): Short =
safeDecodePrimitive(Short.SIZE_BYTES, 0, MavDataDecoder::decodeShort)
/**
* Reads a [UShort]/UInt16 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt16(): UShort =
safeDecodePrimitive(UShort.SIZE_BYTES, 0u, MavDataDecoder::decodeUShort)
/**
* Reads a [Int]/Int32 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt32(): Int =
safeDecodePrimitive(Int.SIZE_BYTES, 0, MavDataDecoder::decodeInt)
/**
* Reads a [UInt]/UInt32 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt32(): UInt =
safeDecodePrimitive(UInt.SIZE_BYTES, 0u, MavDataDecoder::decodeUInt)
/**
* Reads a [Long]/Int64 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt64(): Long =
safeDecodePrimitive(Long.SIZE_BYTES, 0, MavDataDecoder::decodeLong)
/**
* Reads a [ULong]/UInt64 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt64(): ULong =
safeDecodePrimitive(ULong.SIZE_BYTES, 0u, MavDataDecoder::decodeULong)
/**
* Reads a [Float]/Float32 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeFloat(): Float =
safeDecodePrimitive(Float.SIZE_BYTES, 0F) { Float.fromBits(this.decodeInt()) }
/**
* Reads a [Double]/Float64 from the array's current position, and then increments the position. If there are not enough
* bytes in the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeDouble(): Double =
safeDecodePrimitive(Double.SIZE_BYTES, 0.0) { Double.fromBits(this.decodeLong()) }
/**
* Reads a [Char] from the array's current position, and then increments the position. If there are not enough bytes in
* the array, it assumes that the remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeChar(): Char =
if (this.remaining >= Byte.SIZE_BYTES) decodeByte().toInt().toChar() else '\u0000'
/**
* Reads a [String] of the given [length] from the array's current position using the UTF-8 encoding, and then
* increments the position. If there are not enough bytes in the array, the remaining length is ignored.
*/
public fun MavDataDecoder.safeDecodeString(length: Int): String {
val data = ByteArray(length)
if (this.remaining >= length) {
this.decodeByteArray(data)
} else {
this.decodeByteArray(data, 0, this.remaining)
}
for (i in 0 until length) {
if (data[i] == 0.toByte()) return data.decodeToString(0, i)
}
return data.decodeToString()
}
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [Byte]/Int8 values. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt8Array(dataSize: Int): List =
safeDecodeArray(dataSize / Byte.SIZE_BYTES, MavDataDecoder::safeDecodeInt8)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [UByte]/UInt8 values. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt8Array(dataSize: Int): List =
safeDecodeArray(dataSize / UByte.SIZE_BYTES, MavDataDecoder::safeDecodeUInt8)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [Short]/Int16 values. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt16Array(dataSize: Int): List =
safeDecodeArray(dataSize / Short.SIZE_BYTES, MavDataDecoder::safeDecodeInt16)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [UShort]/UInt16 values. If there are not enough bytes in the array, it assumes that the
* remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt16Array(dataSize: Int): List =
safeDecodeArray(dataSize / Short.SIZE_BYTES, MavDataDecoder::safeDecodeUInt16)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [Int]/Int32 values. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt32Array(dataSize: Int): List =
safeDecodeArray(dataSize / Int.SIZE_BYTES, MavDataDecoder::safeDecodeInt32)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [UInt]/UInt32 values. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt32Array(dataSize: Int): List =
safeDecodeArray(dataSize / Int.SIZE_BYTES, MavDataDecoder::safeDecodeUInt32)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [Long]/Int64 values. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeInt64Array(dataSize: Int): List =
safeDecodeArray(dataSize / Long.SIZE_BYTES, MavDataDecoder::safeDecodeInt64)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [ULong]/UInt64 values. If there are not enough bytes in the array, it assumes that the
* remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUInt64Array(dataSize: Int): List =
safeDecodeArray(dataSize / Long.SIZE_BYTES, MavDataDecoder::safeDecodeUInt64)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [Float]/Float32 values. If there are not enough bytes in the array, it assumes that the
* remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeFloatArray(dataSize: Int): List =
safeDecodeArray(dataSize / Float.SIZE_BYTES, MavDataDecoder::safeDecodeFloat)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [List] of the decoded [Double]/Float64 values. If there are not enough bytes in the array, it assumes that the
* remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeDoubleArray(dataSize: Int): List =
safeDecodeArray(dataSize / Double.SIZE_BYTES, MavDataDecoder::safeDecodeDouble)
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [UInt] representing the MAVLink enum value. If there are not enough bytes in the array, it assumes that the remaining
* length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeEnumValue(dataSize: Int): UInt = when (dataSize) {
UByte.SIZE_BYTES -> safeDecodeUInt8().toUInt()
UShort.SIZE_BYTES -> safeDecodeUInt16().toUInt()
UInt.SIZE_BYTES -> safeDecodeUInt32()
ULong.SIZE_BYTES -> safeDecodeUInt64().toUInt()
else -> safeDecodeUnsignedInteger(dataSize).toUInt()
}
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns a
* [UInt] representing the MAVLink bitmask value. If there are not enough bytes in the array, it assumes that the
* remaining length is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeBitmaskValue(dataSize: Int): UInt = when (dataSize) {
UByte.SIZE_BYTES -> safeDecodeUInt8().toUInt()
UShort.SIZE_BYTES -> safeDecodeUInt16().toUInt()
UInt.SIZE_BYTES -> safeDecodeUInt32()
ULong.SIZE_BYTES -> safeDecodeUInt64().toUInt()
else -> safeDecodeUnsignedInteger(dataSize).toUInt()
}
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns the
* unsigned value encoded as a [Long]. If there are not enough bytes in the array, it assumes that the remaining length
* is padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeUnsignedInteger(dataSize: Int): Long {
val data = ByteArray(dataSize)
if (this.remaining >= dataSize) {
this.decodeByteArray(data)
} else {
this.decodeByteArray(data, offset = 0, length = this.remaining)
}
var value: Long = 0
for (i in 0 until dataSize) {
value = value or ((data[i].toLong() and 0xFF.toLong()) shl (i * Byte.SIZE_BITS))
}
return value
}
/**
* Reads [dataSize] number of bytes from the array's current position, and then increments the position. Returns the
* signed value encoded as [Long]. If there are not enough bytes in the array, it assumes that the remaining length is
* padded with zeroes.
*/
public fun MavDataDecoder.safeDecodeSignedInteger(dataSize: Int): Long {
var value = safeDecodeUnsignedInteger(dataSize)
val signBitIndex = dataSize * Byte.SIZE_BITS - 1
if ((value shr signBitIndex) == 1L) {
value = value or (-1L shl signBitIndex)
}
return value
}
private inline fun MavDataDecoder.safeDecodePrimitive(
size: Int,
default: T,
decode: MavDataDecoder.() -> T
): T {
if (this.remaining == 0) {
return default
}
if (this.remaining >= size) {
return this.decode()
}
val rem = ByteArray(size)
this.decodeByteArray(rem, offset = 0, length = this.remaining)
return MavDataDecoder(rem).decode()
}
private inline fun MavDataDecoder.safeDecodeArray(
elementCount: Int,
decode: MavDataDecoder.() -> T
): List =
List(elementCount) { this.decode() }
private fun MavDataDecoder.decodeUByte(): UByte = this.decodeByte().toUByte()
private fun MavDataDecoder.decodeUShort(): UShort = this.decodeShort().toUShort()
private fun MavDataDecoder.decodeUInt(): UInt = this.decodeInt().toUInt()
private fun MavDataDecoder.decodeULong(): ULong = this.decodeLong().toULong()
© 2015 - 2025 Weber Informatics LLC | Privacy Policy