Added updates and Version info
This commit is contained in:
parent
37ebd30cf3
commit
77a5b1285d
|
@ -113,6 +113,8 @@ tasks.jar.get().apply {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.dorkbox:Updates:1.1")
|
||||
|
||||
// listed as compileOnly, since we will be using netty bytebuf utils if we ALREADY are using netty byte buffs. **We don't want a hard dependency.**
|
||||
compileOnly("io.netty:netty-buffer:4.1.66.Final")
|
||||
compileOnly("com.esotericsoftware:kryo:5.2.0")
|
||||
|
|
|
@ -17,8 +17,14 @@
|
|||
* Converted to kotlin by ligi
|
||||
* https://github.com/komputing/KBase58/blob/master/kbase58/src/main/kotlin/org/komputing/kbase58/Base58.kt
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package dorkbox.bytes
|
||||
|
||||
import dorkbox.bytes.Base58.CHECKSUM_SIZE
|
||||
import dorkbox.bytes.Base58.ENCODED_ZERO
|
||||
import dorkbox.bytes.Base58.divmod
|
||||
|
||||
/**
|
||||
* Base58 is a way to encode Bitcoin addresses (or arbitrary data) as alphanumeric strings.
|
||||
* <p>
|
||||
|
@ -43,38 +49,50 @@ package dorkbox.bytes
|
|||
* number of leading zeros (which are otherwise lost during the mathematical operations on the
|
||||
* numbers), and finally represent the resulting base-58 digits as alphanumeric ASCII characters.
|
||||
*/
|
||||
object Base58 {
|
||||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
const val version = BytesInfo.version
|
||||
|
||||
private const val ENCODED_ZERO = '1'
|
||||
private const val CHECKSUM_SIZE = 4
|
||||
|
||||
private const val alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
private val alphabetIndices by lazy {
|
||||
IntArray(128) { alphabet.indexOf(it.toChar()) }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Divides a number, represented as an array of bytes each containing a single digit
|
||||
* in the specified base, by the given divisor. The given number is modified in-place
|
||||
* to contain the quotient, and the return value is the remainder.
|
||||
*
|
||||
* @param number the number to divide
|
||||
* @param firstDigit the index within the array of the first non-zero digit
|
||||
* (this is used for optimization by skipping the leading zeros)
|
||||
* @param base the base in which the number's digits are represented (up to 256)
|
||||
* @param divisor the number to divide by (up to 256)
|
||||
* @return the remainder of the division operation
|
||||
*/
|
||||
private fun divmod(number: ByteArray, firstDigit: UInt, base: UInt, divisor: UInt): UInt {
|
||||
// this is just long division which accounts for the base of the input digits
|
||||
var remainder = 0.toUInt()
|
||||
for (i in firstDigit until number.size.toUInt()) {
|
||||
val digit = number[i.toInt()].toUByte()
|
||||
val temp = remainder * base + digit
|
||||
number[i.toInt()] = (temp / divisor).toByte()
|
||||
remainder = temp % divisor
|
||||
init {
|
||||
// Add this project to the updates system, which verifies this class + UUID + version information
|
||||
dorkbox.updates.Updates.add(Base58::class.java, "f176cecea06e48e1a96d59c08a6e98c3", BytesInfo.version)
|
||||
}
|
||||
|
||||
|
||||
internal const val ENCODED_ZERO = '1'
|
||||
internal const val CHECKSUM_SIZE = 4
|
||||
|
||||
internal const val alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
internal val alphabetIndices by lazy {
|
||||
IntArray(128) { alphabet.indexOf(it.toChar()) }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Divides a number, represented as an array of bytes each containing a single digit
|
||||
* in the specified base, by the given divisor. The given number is modified in-place
|
||||
* to contain the quotient, and the return value is the remainder.
|
||||
*
|
||||
* @param number the number to divide
|
||||
* @param firstDigit the index within the array of the first non-zero digit
|
||||
* (this is used for optimization by skipping the leading zeros)
|
||||
* @param base the base in which the number's digits are represented (up to 256)
|
||||
* @param divisor the number to divide by (up to 256)
|
||||
* @return the remainder of the division operation
|
||||
*/
|
||||
internal fun divmod(number: ByteArray, firstDigit: UInt, base: UInt, divisor: UInt): UInt {
|
||||
// this is just long division which accounts for the base of the input digits
|
||||
var remainder = 0.toUInt()
|
||||
for (i in firstDigit until number.size.toUInt()) {
|
||||
val digit = number[i.toInt()].toUByte()
|
||||
val temp = remainder * base + digit
|
||||
number[i.toInt()] = (temp / divisor).toByte()
|
||||
remainder = temp % divisor
|
||||
}
|
||||
return remainder
|
||||
}
|
||||
return remainder
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,33 +102,37 @@ private fun divmod(number: ByteArray, firstDigit: UInt, base: UInt, divisor: UIn
|
|||
* @return the base58-encoded string
|
||||
*/
|
||||
fun ByteArray.encodeToBase58String(): String {
|
||||
|
||||
val input = copyOf(size) // since we modify it in-place
|
||||
if (input.isEmpty()) {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Count leading zeros.
|
||||
var zeros = 0
|
||||
while (zeros < input.size && input[zeros].toInt() == 0) {
|
||||
++zeros
|
||||
}
|
||||
|
||||
// Convert base-256 digits to base-58 digits (plus conversion to ASCII characters)
|
||||
val encoded = CharArray(input.size * 2) // upper bound
|
||||
var outputStart = encoded.size
|
||||
var inputStart = zeros
|
||||
while (inputStart < input.size) {
|
||||
encoded[--outputStart] = alphabet[divmod(input, inputStart.toUInt(), 256.toUInt(), 58.toUInt()).toInt()]
|
||||
encoded[--outputStart] = Base58.alphabet[Base58.divmod(input, inputStart.toUInt(), 256.toUInt(), 58.toUInt()).toInt()]
|
||||
if (input[inputStart].toInt() == 0) {
|
||||
++inputStart // optimization - skip leading zeros
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve exactly as many leading encoded zeros in output as there were leading zeros in data.
|
||||
while (outputStart < encoded.size && encoded[outputStart] == ENCODED_ZERO) {
|
||||
++outputStart
|
||||
}
|
||||
|
||||
while (--zeros >= 0) {
|
||||
encoded[--outputStart] = ENCODED_ZERO
|
||||
encoded[--outputStart] = Base58.ENCODED_ZERO
|
||||
}
|
||||
|
||||
// Return encoded string (including encoded leading zeros).
|
||||
return String(encoded, outputStart, encoded.size - outputStart)
|
||||
}
|
||||
|
@ -126,21 +148,24 @@ fun String.decodeBase58(): ByteArray {
|
|||
if (isEmpty()) {
|
||||
return ByteArray(0)
|
||||
}
|
||||
|
||||
// Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits).
|
||||
val input58 = ByteArray(length)
|
||||
for (i in 0 until length) {
|
||||
val c = this[i]
|
||||
val digit = if (c.toInt() < 128) alphabetIndices[c.toInt()] else -1
|
||||
val digit = if (c.code < 128) Base58.alphabetIndices[c.toInt()] else -1
|
||||
if (digit < 0) {
|
||||
throw NumberFormatException("Illegal character $c at position $i")
|
||||
}
|
||||
input58[i] = digit.toByte()
|
||||
}
|
||||
|
||||
// Count leading zeros.
|
||||
var zeros = 0
|
||||
while (zeros < input58.size && input58[zeros].toInt() == 0) {
|
||||
++zeros
|
||||
}
|
||||
|
||||
// Convert base-58 digits to base-256 digits.
|
||||
val decoded = ByteArray(length)
|
||||
var outputStart = decoded.size
|
||||
|
@ -151,10 +176,12 @@ fun String.decodeBase58(): ByteArray {
|
|||
++inputStart // optimization - skip leading zeros
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore extra leading zeroes that were added during the calculation.
|
||||
while (outputStart < decoded.size && decoded[outputStart].toInt() == 0) {
|
||||
++outputStart
|
||||
}
|
||||
|
||||
// Return decoded data (including original number of leading zeros).
|
||||
return decoded.copyOfRange(outputStart - zeros, decoded.size)
|
||||
}
|
||||
|
@ -164,21 +191,21 @@ fun String.decodeBase58(): ByteArray {
|
|||
*
|
||||
* @return the base58-encoded string
|
||||
*/
|
||||
fun ByteArray.encodeToBase58WithChecksum() = ByteArray(size + CHECKSUM_SIZE).apply {
|
||||
fun ByteArray.encodeToBase58WithChecksum() = ByteArray(size + Base58.CHECKSUM_SIZE).apply {
|
||||
System.arraycopy(this@encodeToBase58WithChecksum, 0, this, 0, this@encodeToBase58WithChecksum.size)
|
||||
val checksum = this@encodeToBase58WithChecksum.sha256().sha256()
|
||||
System.arraycopy(checksum, 0, this, this@encodeToBase58WithChecksum.size, CHECKSUM_SIZE)
|
||||
System.arraycopy(checksum, 0, this, this@encodeToBase58WithChecksum.size, Base58.CHECKSUM_SIZE)
|
||||
|
||||
}.encodeToBase58String()
|
||||
|
||||
fun String.decodeBase58WithChecksum(): ByteArray {
|
||||
val rawBytes = decodeBase58()
|
||||
if (rawBytes.size < CHECKSUM_SIZE) {
|
||||
if (rawBytes.size < Base58.CHECKSUM_SIZE) {
|
||||
throw Exception("Too short for checksum: $this l: ${rawBytes.size}")
|
||||
}
|
||||
val checksum = rawBytes.copyOfRange(rawBytes.size - CHECKSUM_SIZE, rawBytes.size)
|
||||
val checksum = rawBytes.copyOfRange(rawBytes.size - Base58.CHECKSUM_SIZE, rawBytes.size)
|
||||
|
||||
val payload = rawBytes.copyOfRange(0, rawBytes.size - CHECKSUM_SIZE)
|
||||
val payload = rawBytes.copyOfRange(0, rawBytes.size - Base58.CHECKSUM_SIZE)
|
||||
|
||||
val hash = payload.sha256().sha256()
|
||||
val computedChecksum = hash.copyOfRange(0, CHECKSUM_SIZE)
|
||||
|
|
|
@ -62,15 +62,25 @@ import java.io.InputStream
|
|||
* Modified from KRYO ByteBufferInput to use ByteBuf instead of ByteBuffer.
|
||||
*/
|
||||
class ByteBufInput : Input {
|
||||
companion object {
|
||||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
const val version = BytesInfo.version
|
||||
|
||||
init {
|
||||
// Add this project to the updates system, which verifies this class + UUID + version information
|
||||
dorkbox.updates.Updates.add(ByteBufInput::class.java, "f176cecea06e48e1a96d59c08a6e98c3", BytesInfo.version)
|
||||
}
|
||||
}
|
||||
|
||||
var byteBuf: ByteBuf? = null
|
||||
private set
|
||||
|
||||
private var initialReaderIndex = 0
|
||||
private var initialWriterIndex = 0
|
||||
private var tempBuffer: ByteArray? = null
|
||||
|
||||
/** Creates an uninitialized Input, [.setBuffer] must be called before the Input is used. */
|
||||
constructor() {}
|
||||
|
||||
/** Creates a new Input for reading from a direct [ByteBuf].
|
||||
* @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are read and
|
||||
* [.fill] does not supply more bytes.
|
||||
|
@ -83,7 +93,6 @@ class ByteBufInput : Input {
|
|||
* @see .setBuffer
|
||||
*/
|
||||
/** Creates a new Input for reading from a [ByteBuf] which is filled with the specified bytes. */
|
||||
@JvmOverloads
|
||||
constructor(bytes: ByteArray?, offset: Int = 0, count: Int = bytes!!.size) {
|
||||
requireNotNull(bytes) { "bytes cannot be null." }
|
||||
setBuffer(Unpooled.wrappedBuffer(bytes, offset, count))
|
||||
|
@ -111,7 +120,9 @@ class ByteBufInput : Input {
|
|||
/** Throws [UnsupportedOperationException] because this input uses a ByteBuffer, not a byte[].
|
||||
* @see .getByteBuf
|
||||
*/
|
||||
@Deprecated(" ")
|
||||
@Deprecated("Use getByteBuf() instead",
|
||||
ReplaceWith("getByteBuf()")
|
||||
)
|
||||
override fun getBuffer(): ByteArray {
|
||||
throw UnsupportedOperationException("This input does not used a byte[], see #getByteBuf().")
|
||||
}
|
||||
|
@ -119,7 +130,9 @@ class ByteBufInput : Input {
|
|||
/** Throws [UnsupportedOperationException] because this input uses a ByteBuffer, not a byte[].
|
||||
* @see .setBuffer
|
||||
*/
|
||||
@Deprecated(" ")
|
||||
@Deprecated("Use setByteBuf() instead",
|
||||
ReplaceWith("setByteBuf(ByteBuf)")
|
||||
)
|
||||
override fun setBuffer(bytes: ByteArray) {
|
||||
throw UnsupportedOperationException("This input does not used a byte[], see #setByteBuf(ByteBuf).")
|
||||
}
|
||||
|
|
|
@ -62,10 +62,23 @@ import java.io.OutputStream
|
|||
* Modified from KRYO to use ByteBuf.
|
||||
*/
|
||||
class ByteBufOutput : Output {
|
||||
companion object {
|
||||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
const val version = BytesInfo.version
|
||||
|
||||
init {
|
||||
// Add this project to the updates system, which verifies this class + UUID + version information
|
||||
dorkbox.updates.Updates.add(ByteBufOutput::class.java, "f176cecea06e48e1a96d59c08a6e98c3", BytesInfo.version)
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the buffer. The bytes between zero and [.position] are the data that has been written. */
|
||||
// NOTE: capacity IS NOT USED!
|
||||
var byteBuf: ByteBuf? = null
|
||||
private set
|
||||
|
||||
private var initialReaderIndex = 0
|
||||
private var initialWriterIndex = 0
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright 2021 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -52,6 +52,16 @@ import kotlin.experimental.and
|
|||
@Suppress("unused", "DuplicatedCode", "DuplicatedCode", "MemberVisibilityCanBePrivate")
|
||||
class ByteBuffer2 {
|
||||
companion object {
|
||||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
const val version = BytesInfo.version
|
||||
|
||||
init {
|
||||
// Add this project to the updates system, which verifies this class + UUID + version information
|
||||
dorkbox.updates.Updates.add(ByteBuffer2::class.java, "f176cecea06e48e1a96d59c08a6e98c3", BytesInfo.version)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that would be written with [.writeInt].
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2021 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
|
||||
|
||||
object BytesInfo {
|
||||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
const val version = "1.2"
|
||||
}
|
|
@ -1,3 +1,18 @@
|
|||
/*
|
||||
* Copyright 2021 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
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
|
|
@ -27,6 +27,16 @@ package dorkbox.bytes
|
|||
public value class HexString(val string: String)
|
||||
|
||||
object Hex {
|
||||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
const val version = BytesInfo.version
|
||||
|
||||
init {
|
||||
// Add this project to the updates system, which verifies this class + UUID + version information
|
||||
dorkbox.updates.Updates.add(Hex::class.java, "f176cecea06e48e1a96d59c08a6e98c3", BytesInfo.version)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents all the chars used for nibble
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module dorkbox.bytes {
|
||||
exports dorkbox.bytes;
|
||||
|
||||
requires dorkbox.updates;
|
||||
|
||||
requires static com.esotericsoftware.kryo;
|
||||
requires static io.netty.common;
|
||||
requires static io.netty.buffer;
|
||||
|
|
Loading…
Reference in New Issue