package com.infendro.bytes.ubytearray fun UByteArray.invInto( destination: UByteArray, 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)) repeat(length) { i -> destination[destinationOffset + i] = this[startIndex + i].inv() } } fun UByteArray.inv() = UByteArray(size).also { invInto(it) } private inline fun UByteArray.combineInto( that: UByteArray, destination: UByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, combine: (UByte, UByte) -> UByte, ) { 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)) repeat(length) { i -> destination[destinationOffset + i] = combine(this[startIndex + i], that[thatStartIndex + i]) } } private inline fun UByteArray.combine( that: UByteArray, combine: (UByte, UByte) -> UByte, ): UByteArray { require(this.size == that.size) return UByteArray(size).also { combineInto(that, it, combine = combine) } } fun UByteArray.andInto( that: UByteArray, destination: UByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, ) = combineInto( that, destination, destinationOffset, startIndex, endIndex, thatStartIndex, ) { a, b -> a and b } infix fun UByteArray.and(that: UByteArray) = combine(that) { a, b -> a and b } fun UByteArray.orInto( that: UByteArray, destination: UByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, ) = combineInto( that, destination, destinationOffset, startIndex, endIndex, thatStartIndex, ) { a, b -> a or b } infix fun UByteArray.or(that: UByteArray) = combine(that) { a, b -> a or b } fun UByteArray.xorInto( that: UByteArray, destination: UByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size, thatStartIndex: Int = 0, ) = combineInto( that, destination, destinationOffset, startIndex, endIndex, thatStartIndex, ) { a, b -> a xor b } infix fun UByteArray.xor(that: UByteArray) = combine(that) { a, b -> a xor b }