package com.infendro.bytes.bytearray import com.infendro.bytes.byte.not import kotlin.experimental.and import kotlin.experimental.or import kotlin.experimental.xor private inline fun ByteArray.combineInto( that: ByteArray, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, combine: (Byte, Byte) -> Byte, ) { val length = endIndex - startIndex require(length >= 0) require(startIndex in 0..(size - length)) require(thatStartIndex in 0..(that.size - length)) require(destinationOffset in 0..(destination.size - length)) for (i in 0.. Byte, ) { val length = endIndex - startIndex require(length >= 0) require(startIndex in 0..(size - length)) require(destinationOffset in 0..(destination.size - length)) for (i in 0.. Byte): ByteArray { require(this.size == that.size) val result = ByteArray(size) combineInto(that, result, combine = combine) return result } private inline fun ByteArray.combine(that: Byte, combine: (Byte, Byte) -> Byte): ByteArray { val result = ByteArray(size) combineInto(that, result, combine = combine) return result } fun ByteArray.andInto( that: ByteArray, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, ) { combineInto(that, destination, destinationOffset, startIndex, endIndex, thatStartIndex) { a, b -> a and b } } fun ByteArray.andInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) { andInto(destination, destination, destinationOffset, startIndex, endIndex, destinationOffset) } fun ByteArray.andInto( that: Byte, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, ) { combineInto(that, destination, destinationOffset, startIndex, endIndex) { a, b -> a and b } } infix fun ByteArray.and(that: ByteArray): ByteArray { return combine(that) { a, b -> a and b } } infix fun ByteArray.and(that: Byte): ByteArray { return combine(that) { a, b -> a and b } } fun ByteArray.orInto( that: ByteArray, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, ) { combineInto(that, destination, destinationOffset, startIndex, endIndex, thatStartIndex) { a, b -> a or b } } fun ByteArray.orInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) { orInto(destination, destination, destinationOffset, startIndex, endIndex, destinationOffset) } fun ByteArray.orInto( that: Byte, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, ) { combineInto(that, destination, destinationOffset, startIndex, endIndex) { a, b -> a or b } } infix fun ByteArray.or(that: ByteArray): ByteArray { return combine(that) { a, b -> a or b } } infix fun ByteArray.or(that: Byte): ByteArray { return combine(that) { a, b -> a or b } } fun ByteArray.xorInto( that: ByteArray, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, ) { combineInto(that, destination, destinationOffset, startIndex, endIndex, thatStartIndex) { a, b -> a xor b } } fun ByteArray.xorInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) { xorInto(destination, destination, destinationOffset, startIndex, endIndex, destinationOffset) } fun ByteArray.xorInto( that: Byte, destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, ) { combineInto(that, destination, destinationOffset, startIndex, endIndex) { a, b -> a xor b } } infix fun ByteArray.xor(that: ByteArray): ByteArray { return combine(that) { a, b -> a xor b } } infix fun ByteArray.xor(that: Byte): ByteArray { return combine(that) { a, b -> a xor b } } fun ByteArray.invInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) { val length = endIndex - startIndex require(length >= 0) require(startIndex in 0..(size - length)) require(destinationOffset in 0..(destination.size - length)) for (i in 0..