Created
September 24, 2021 10:38
-
-
Save andy722/46bc7f1d8caa2c6e9b4cd74f3a5e0dfa to your computer and use it in GitHub Desktop.
UUIDv4 with custom payload
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 com.google.common.base.Preconditions | |
import java.nio.ByteBuffer | |
import static com.google.common.base.Preconditions.checkState | |
// See java.util.UUID#randomUUID | |
UUID generateV4(byte[] src) { | |
checkState src.length <= 14 | |
// Enrich initial payload w/ version and variant for a proper UUID type | |
final byte[] dst = new byte[16].tap { dst -> | |
final copy = { int iDst, int iSrc -> | |
// Debug | |
// println "dst[$iDst] = src[$iSrc]" | |
dst[iDst] = iSrc < src.length ? src[iSrc] : (byte) 0 | |
} | |
int iSrc = 0, iDst = 0 | |
// Bytes 0..5 | |
for (; iDst < 6; iSrc++, iDst++) copy iDst, iSrc | |
// Byte 6 | |
dst[6] &= 0x0f /* clear version */ | |
dst[6] |= 0x40 /* set to version 4 */ | |
iDst++ | |
// Byte 7 | |
copy iDst++, iSrc++ | |
// Byte 8 | |
dst[8] &= 0x3f /* clear variant */ | |
dst[8] |= 0x80 /* set to IETF variant */ | |
iDst++ | |
// Byte 9..15 | |
for (; iDst < 16; iSrc++, iDst++) copy iDst, iSrc | |
} | |
new UUID(dst) | |
} | |
// Read initial payload skipping version and variant | |
byte getPayload(UUID uuid) { | |
final src = ByteBuffer.wrap(new byte[16]) | |
.tap { | |
putLong(uuid.mostSignificantBits) | |
putLong(uuid.leastSignificantBits) | |
} | |
.array() | |
// Read initial payload skipping version and variant | |
return new byte[14].tap { dst -> | |
final copy = { int iDst, int iSrc -> | |
// Debug | |
// println "dst[$iDst] = src[$iSrc]" | |
dst[iDst] = iSrc < src.length ? src[iSrc] : (byte) 0 | |
} | |
int iSrc = 0, iDst = 0 | |
// Bytes 0..5 | |
for (; iDst < 6; iSrc++, iDst++) copy iDst, iSrc | |
// Byte 6: version | |
iSrc++ | |
// Byte 7 | |
copy iDst++, iSrc++ | |
// Byte 8: variant | |
iSrc++ | |
// Byte 9..15 | |
for (; iSrc < 16; iSrc++, iDst++) copy iDst, iSrc | |
} | |
} | |
// | |
// Specific usage | |
// | |
UUID getWaybillEventId(Long waybillId, int eventType) { | |
final buf = ByteBuffer.allocate(14).tap { | |
putLong waybillId // 8 | |
putInt eventType // 4 | |
} | |
generateV4 buf.array() | |
} | |
Tuple2<Long, Integer> parseWaybillEventId(UUID uuid) { | |
final dst = getPayload uuid | |
ByteBuffer.wrap(dst).with { | |
Tuple.tuple( | |
it.long, | |
it.int | |
) | |
} | |
} | |
long waybillId = 999999999999999999L | |
int eventType = 1I | |
final uuid = getWaybillEventId(waybillId, eventType) | |
println "waybillId: $waybillId, eventType:$eventType -> $uuid (version: ${uuid.version()}, variant: ${uuid.variant()})" | |
assert uuid.version() == 4 | |
final parsed = parseWaybillEventId(uuid) | |
println "uuid $uuid -> waybillId: $parsed.v1, eventType:$parsed.v2" | |
assert parsed.v1 == waybillId | |
assert parsed.v2 == eventType |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment