JavaScript/TypeScript:将UUID从最高有效位(MSB)/最低有效位(LSB)表示转换为字符串.&l



为了在使用协议缓冲区传递uuid时节省空间,我们使用MSB/LSB表示发送它们,两个64位long

message Uuid {
sfixed64 msb = 1;
sfixed64 lsb = 2;
} 

这些在Java中很容易来回,

UUID id = UUID.fromString("eb66c416-4739-465b-9af3-9dc33ed8eef9");
long msb = id.getMostSignificantBits();
long lsb = id.getLeastSignificantBits();
System.out.println(msb + ", " + lsb);
// -1484283427208739237, -7281302710629372167
System.out.println(new UUID(msb, lsb));
// eb66c416-4739-465b-9af3-9dc33ed8eef9

然而,由于JavaScript的number只能达到253- 1,我无法在我的TypeScript客户端中将MSB/LSB格式转换回string。这可能吗?

看JavaUUIDtoString()方法的启发,

public String toString() {
return (digits(mostSigBits >> 32, 8) + "-" +
digits(mostSigBits >> 16, 4) + "-" +
digits(mostSigBits, 4) + "-" +
digits(leastSigBits >> 48, 4) + "-" +
digits(leastSigBits, 12));
}
private static String digits(long val, int digits) {
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}

我们可以使用BigInt做同样的事情。这里假设Node 10.8+(在18.14.0上测试),TypeScript的目标是ES2020+,并且与此浏览器兼容。

注意:如果您得到"BigInt字面量不可用…"将所有以n结尾的字面值用BigInt代替(例如,用BigInt(32)代替32n)。

function uuidSigBitsToStr({ lsb, msb }: { lsb: bigint; msb: bigint }): string {
return `${digits(msb >> 32n, 8n)}-${digits(msb >> 16n, 4n)}-${digits(
msb,
4n
)}-${digits(lsb >> 48n, 4n)}-${digits(lsb, 12n)}`;
}
function digits(val: bigint, ds: bigint): string {
const hi = 1n << (ds * 4n);
return (hi | (val & (hi - 1n))).toString(16).substring(1);
}

和一个示例测试,注意msb/lsb作为strings传递给BigInt

it('converts UUID from msb/lsb to string', () => {
expect(
toUuidString(
BigInt('-1160168401362026442'),
BigInt('-6694969989912915968')
)
).toEqual('a316b044-0157-1000-efe6-40fc5d2f0036');
});

最后一部分是协议缓冲区。默认情况下,google-protobuf对64位floatint的值使用number,导致Number.MAX_VALUE以上溢出或253- 1。为了避免这种情况,在64位字段上使用jstype注释

message Uuid {
sfixed64 msb = 1 [jstype = JS_STRING];
sfixed64 lsb = 2 [jstype = JS_STRING];
} 

2023更新:反向功能,从UUID字符串转换为有效位

function uuidStrToSigBits(uuid: string) {
const invalidError = () => new Error(`Invalid UUID string: '${uuid}'`);
if (uuid == null || typeof uuid !== "string") throw invalidError();
const parts = uuid.split("-").map((p) => `0x${p}`);
if (parts.length !== 5) throw invalidError();
return {
lsb: (hexStrToBigInt(parts[3]) << 48n) | hexStrToBigInt(parts[4]),
msb:
(hexStrToBigInt(parts[0]) << 32n) |
(hexStrToBigInt(parts[1]) << 16n) |
hexStrToBigInt(parts[2]),
};
}
function hexStrToBigInt(hex: string): bigint {
return BigInt(Number.parseInt(hex, 16));
}

这是一个往返测试,

const uuidSigBits = uuidStrToSigBits("7680fc63-1f58-412a-9bde-c5a9de1e0ce9");
const uuidStr = uuidSigBitsToStr(uuidSigBits);
console.log(uuidStr);
// => 7680fc63-1f58-412a-9bde-c5a9de1e0ce9

相关内容

  • 没有找到相关文章

最新更新