PasswordTreePayloadValidation.kt
package de.pflugradts.passbird.application.passwordtree
import de.pflugradts.passbird.domain.model.slot.Slot
internal fun validatePayloadEnvelope(bytes: ByteArray) {
if (bytes.size < signatureSize() + checksumBytes()) {
throwUnsupportedPasswordTreeFormat()
}
}
internal fun payloadContentEnd(bytes: ByteArray) = bytes.size - checksumBytes()
internal fun readPayloadInt(bytes: ByteArray, offset: Int, limitExclusive: Int = bytes.size): Int {
validatePayloadRange(bytes, offset, Integer.BYTES, limitExclusive)
return ((bytes[offset].toInt() and 0xFF) shl 24) or
((bytes[offset + 1].toInt() and 0xFF) shl 16) or
((bytes[offset + 2].toInt() and 0xFF) shl 8) or
(bytes[offset + 3].toInt() and 0xFF)
}
internal fun readPayloadSize(bytes: ByteArray, offset: Int, limitExclusive: Int = bytes.size): Int =
readPayloadInt(bytes, offset, limitExclusive).also {
if (it < 0) {
throwUnsupportedPasswordTreeFormat()
}
}
internal fun readPayloadBytes(bytes: ByteArray, offset: Int, size: Int, limitExclusive: Int = bytes.size): ByteArray {
validatePayloadRange(bytes, offset, size, limitExclusive)
return bytes.copyOfRange(offset, offset + size)
}
internal fun validatePayloadRange(bytes: ByteArray, offset: Int, size: Int, limitExclusive: Int = bytes.size) {
if (offset < 0 || size < 0) {
throwUnsupportedPasswordTreeFormat()
}
if (limitExclusive < 0 || limitExclusive > bytes.size) {
throwUnsupportedPasswordTreeFormat()
}
if (offset > limitExclusive - size) {
throwUnsupportedPasswordTreeFormat()
}
}
internal fun validatePayloadEnd(offset: Int, endExclusive: Int) {
if (offset != endExclusive) {
throwUnsupportedPasswordTreeFormat()
}
}
internal fun storedEggNestSlot(index: Int): Slot {
if (index != Slot.DEFAULT.index() && index !in Slot.FIRST_SLOT..Slot.LAST_SLOT) {
throwUnsupportedPasswordTreeFormat()
}
return Slot.slotAt(index)
}
internal fun throwUnsupportedPasswordTreeFormat(): Nothing = throw IllegalStateException("Unsupported password tree format.")