ByteUtilities/src/dorkbox/bytes/ByteArrayWrapper.kt

93 lines
2.7 KiB
Kotlin

/*
* Copyright 2023 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.bytes
/**
* Necessary to provide equals and hashcode methods on a byte arrays, if they are to be used as keys in a map/set/etc
*/
class ByteArrayWrapper(
data: ByteArray,
/**
* if TRUE, then the byteArray is copied. if FALSE, the byte array is used as-is.
*
* Using FALSE IS DANGEROUS!!!! If the underlying byte array is modified, this changes as well.
*/
copyBytes: Boolean = true
) {
companion object {
/**
* Gets the version number.
*/
const val version = BytesInfo.version
/**
* Makes a safe copy of the byte array, so that changes to the original do not affect the wrapper.
* One side effect is that additional memory is used.
*/
fun copy(data: ByteArray): ByteArrayWrapper {
return ByteArrayWrapper(data, true)
}
/**
* Does not make a copy of the data, so changes to the original will also affect the wrapper.
* One side effect is that no extra memory is needed.
*/
fun wrap(data: ByteArray): ByteArrayWrapper {
return ByteArrayWrapper(data, false)
}
}
val bytes: ByteArray
private var hashCode: Int? = null
init {
val length = data.size
if (copyBytes) {
bytes = ByteArray(length)
// copy so it's immutable as a key.
System.arraycopy(data, 0, bytes, 0, length)
} else {
bytes = data
}
}
override fun hashCode(): Int {
// might be null for a thread because it's stale. who cares, get the value again
var hashCode = hashCode
if (hashCode == null) {
hashCode = bytes.contentHashCode()
this.hashCode = hashCode
}
return hashCode
}
override fun equals(other: Any?): Boolean {
return if (other !is ByteArrayWrapper) {
false
} else bytes.contentEquals(other.bytes)
// CANNOT be null, so we don't have to null check!
}
override fun toString(): String {
return "ByteArrayWrapper " + bytes.contentToString()
}
}