Last active
May 3, 2023 18:09
-
-
Save L-Briand/f15d863ef64e5fd91dddca6cd2928cfe to your computer and use it in GitHub Desktop.
Helper class to work with hexadecimal strings.
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 kotlinx.serialization.Serializable | |
/** | |
* Utility class to work with hexadecimal strings. | |
* | |
* Two hex values with same [raw] should be equals. | |
* Even if one was created with lower cased hex and the other with upper cased hex. | |
* | |
* It contains : | |
* - static helpers to encode [fromString] and decode [toString] in hexadecimal strings. | |
* - static helper [of] to safely get a [HexValue] from an hexadecimal string. | |
* - [toString] outputs upper cased hexadecimal string of [raw] | |
* | |
*/ | |
@Serializable(HexValueSerializer::class) | |
class HexValue(val raw: ByteArray) { | |
constructor(string: CharSequence) : this(fromString(string)!!) | |
companion object { | |
private val upper = "0123456789ABCDEF".toByteArray(Charsets.US_ASCII) | |
private val lower = "0123456789abcdef".toByteArray(Charsets.US_ASCII) | |
/** | |
* Convert [value] into hexadecimal [String] | |
* | |
* @param upperCase true to get upper case hexadecimal string, false to get lower case hexadecimal string | |
* | |
* @return hexadecimal string | |
*/ | |
fun toString(value: ByteArray, upperCase: Boolean): String { | |
val hexString = ByteArray(value.size * 2) | |
val source = if (upperCase) upper else lower | |
for (idx in value.indices) { | |
val int = value[idx].toInt() and 0xFF | |
hexString[idx * 2] = source[int shr 4] | |
hexString[idx * 2 + 1] = source[int and 0x0F] | |
} | |
return String(hexString, Charsets.UTF_8) | |
} | |
/** | |
* Convert a [value] into [ByteArray] | |
* @return null if the string cannot be parsed as hexadecimal string. | |
*/ | |
fun fromString(value: CharSequence): ByteArray? { | |
if (value.length and 0x1 == 1) return null | |
return try { | |
ByteArray(value.length / 2) { | |
Integer.parseInt(value, it * 2, (it + 1) * 2, 16).toByte() | |
} | |
} catch (e: NumberFormatException) { | |
null | |
} | |
} | |
/** | |
* Getting safely an HexValue from [string] | |
* @return null if the [string] was not an hex value | |
*/ | |
fun of(string: CharSequence?): HexValue? { | |
string ?: return null | |
val raw = fromString(string) ?: return null | |
return HexValue(raw) | |
} | |
} | |
/** Specify with [isUpperCase] if the resulting hexadecimal string should be upper cased or lower cased */ | |
fun toString(isUpperCase: Boolean) = Companion.toString(raw, isUpperCase) | |
override fun toString(): String = toString(false) | |
override fun equals(other: Any?): Boolean { | |
if (this === other) return true | |
if (javaClass != other?.javaClass) return false | |
other as HexValue | |
if (!raw.contentEquals(other.raw)) return false | |
return true | |
} | |
override fun hashCode(): Int { | |
return raw.contentHashCode() | |
} | |
} |
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 kotlinx.serialization.KSerializer | |
import kotlinx.serialization.descriptors.PrimitiveKind | |
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor | |
import kotlinx.serialization.descriptors.SerialDescriptor | |
import kotlinx.serialization.encoding.Decoder | |
import kotlinx.serialization.encoding.Encoder | |
/** | |
* kotlinx serializer for [HexValue]. | |
* Transforms it to json string | |
*/ | |
class HexValueSerializer : KSerializer<HexValue> { | |
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("HexValueSerializer", PrimitiveKind.STRING) | |
override fun deserialize(decoder: Decoder): HexValue = HexValue(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: HexValue) { | |
encoder.encodeString(value.toString()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment