Created
March 30, 2023 03:58
-
-
Save ultraviolet-jordan/e4b743a023532336cb9475c649ce7a17 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.ByteBuffer | |
import kotlin.math.abs | |
fun main() { | |
val expectedInt = 420 | |
val buffer = ByteBuffer.allocate(3) | |
buffer.putAsVl64(expectedInt) | |
buffer.flip() | |
val readInt = buffer.getAsVl64() | |
println("Matches? ${expectedInt == readInt}") | |
} | |
private tailrec fun ByteBuffer.putAsVl64( | |
value: Int, | |
abs: Int = abs(value), | |
position: Int = position(), // The current position of this buffer used to track the prefix byte. | |
size: Int = 1 // Current number of bytes written. | |
): ByteBuffer { | |
if (size == 1) { | |
// Set prefix byte at this current position. This is only called the first iteration. | |
put((64 + (abs and 3)).toByte()) | |
} | |
val nextByte = (abs shr 2) shr (6 * (size - 1)) | |
if (nextByte != 0) { | |
// Append a new byte to the buffer with the next 6 bits of the absolute value. | |
put((64 + (nextByte and 0x3F)).toByte()) | |
return putAsVl64(value, abs, position, size + 1) | |
} | |
// Modify the prefix byte to include the size and sign of the integer. | |
val prefix = get(position).toInt() | |
put(position, (prefix or (size shl 3) or if (value >= 0) 0 else 4).toByte()) | |
return this | |
} | |
private tailrec fun ByteBuffer.getAsVl64( | |
prefix: Int = get().toInt(), // The prefix byte at the first position. | |
value: Int = prefix and 3, // Least significant bits of the first byte | |
position: Int = 1 // Position of the next byte to decode | |
): Int { | |
// The total number of bytes to read. | |
val size = prefix shr 3 and 7 | |
return if (position < size) { | |
// Shift amount for the next byte's bits | |
val shift = 2 + (6 * (position - 1)) | |
val nextByte = get().toInt() and 0x3F | |
val nextValue = (nextByte shl shift) or value | |
getAsVl64(prefix, nextValue, position + 1) | |
} else { | |
if (prefix and 4 == 4) -(value xor ((1 shl (size * 6)) - 1)) else value | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment