Skip to content

Instantly share code, notes, and snippets.

@richardstephens
Created November 8, 2020 20:41
Show Gist options
  • Save richardstephens/d974260678cee5ee2906e71f7f9a8ab4 to your computer and use it in GitHub Desktop.
Save richardstephens/d974260678cee5ee2906e71f7f9a8ab4 to your computer and use it in GitHub Desktop.
Base64 UUID with space for some flags
package dev.richst.libs.richuuid;
import java.io.*;
import java.util.Base64;
import java.util.UUID;
public class RichUuid {
static byte[] uuidToByteArray(UUID uuid) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeLong(uuid.getMostSignificantBits());
dos.writeLong(uuid.getLeastSignificantBits());
dos.write(2);
dos.flush();
return bos.toByteArray();
} catch (IOException ex) {
// this should never be thrown, and there is no sensible way to handle it
throw new IllegalStateException(
"IO exception occurred working on memory backed streams", ex);
}
}
static UUID byteArrayToUuid(byte[] uuidBytes) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(uuidBytes);
DataInputStream dis = new DataInputStream(bis);
long msb = dis.readLong();
long lsb = dis.readLong();
return new UUID(msb, lsb);
} catch (IOException ex) {
// this should never be thrown, and there is no sensible way to handle it
throw new IllegalStateException(
"IO exception occurred working on memory backed streams", ex);
}
}
public static String fromUUID(UUID uuid) {
byte[] uuidBytes = uuidToByteArray(uuid);
byte[] uuidBytesWithChecksum = new byte[18];
int checksum = 0;
for (int ii = 0; ii < 16; ii++) {
uuidBytesWithChecksum[ii] = uuidBytes[ii];
checksum += uuidBytes[ii] & 0xFF;
}
uuidBytesWithChecksum[16] = 0;
uuidBytesWithChecksum[17] = (byte) (checksum % 256);
return Base64.getUrlEncoder().encodeToString(uuidBytesWithChecksum);
}
public static String generate() {
return fromUUID(UUID.randomUUID());
}
private static boolean validateChecksum(byte[] uuidBytesWithChecksum) {
int checksum = 0;
for (int ii = 0; ii < 17; ii++) {
checksum += uuidBytesWithChecksum[ii] & 0xFF;
}
return ((byte) checksum) == uuidBytesWithChecksum[17];
}
private static void assertChecksumValid(byte[] uuidBytes) {
if (!validateChecksum(uuidBytes)) {
throw new InvalidRichUuidException("checksum invalid");
}
}
public static UUID toUUID(String richUuid) {
byte[] uuidBytesWithChecksum;
try {
uuidBytesWithChecksum = Base64.getUrlDecoder().decode(richUuid);
} catch (IllegalArgumentException ex) {
throw new InvalidRichUuidException("Could not base64 decode richUuid", ex);
}
if (uuidBytesWithChecksum.length != 18) {
throw new InvalidRichUuidException("UUID length invalid");
}
assertChecksumValid(uuidBytesWithChecksum);
return byteArrayToUuid(uuidBytesWithChecksum);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment