JavaScript/TypeScript:将 UUID 从最高有效位 (MSB)/最低有效位 (LSB) 表示形式转换为字符串
JavaScript/TypeScript: Convert UUID from most significant bits (MSB)/least significant bits (LSB) representation to string
为了在使用协议缓冲区传递 UUID 时保存 space,我们使用 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
但是,由于 Java脚本的 number
最多只能达到 253 - 1,所以我无法转换 MSB/LSB在我的 TypeScript 客户端中格式化回 string
。这可能吗?
看JavaUUID
的toString()
方法获得灵感,
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
. This assumes Node 10.8+ (tested with 14.15.5), TypeScript targeting ES2020+, and with this browser compatibility 来做同样的事情。
注意:如果您收到“BigInt 文字不可用...”,则将所有以 n
结尾的文字换成 BigInt
(例如,使用 BigInt(32)
).
而不是 32n
export function toUuidString(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 作为 string
s 传递给 BigInt
,
it('converts UUID from msb/lsb to string', () => {
expect(
toUuidString(
BigInt('-1160168401362026442'),
BigInt('-6694969989912915968')
)
).toEqual('a316b044-0157-1000-efe6-40fc5d2f0036');
});
最后一块是协议缓冲区。默认情况下,google-protobuf
对 64 位 float
和 int
值使用 number
,这会导致溢出 Number.MAX_VALUE
或 253 - 1. 为避免这种情况,在 64 位字段上使用 jstype
注释,
message Uuid {
sfixed64 msb = 1 [jstype = JS_STRING];
sfixed64 lsb = 2 [jstype = JS_STRING];
}
为了在使用协议缓冲区传递 UUID 时保存 space,我们使用 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
但是,由于 Java脚本的 number
最多只能达到 253 - 1,所以我无法转换 MSB/LSB在我的 TypeScript 客户端中格式化回 string
。这可能吗?
看JavaUUID
的toString()
方法获得灵感,
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
. This assumes Node 10.8+ (tested with 14.15.5), TypeScript targeting ES2020+, and with this browser compatibility 来做同样的事情。
注意:如果您收到“BigInt 文字不可用...”,则将所有以 n
结尾的文字换成 BigInt
(例如,使用 BigInt(32)
).
32n
export function toUuidString(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 作为 string
s 传递给 BigInt
,
it('converts UUID from msb/lsb to string', () => {
expect(
toUuidString(
BigInt('-1160168401362026442'),
BigInt('-6694969989912915968')
)
).toEqual('a316b044-0157-1000-efe6-40fc5d2f0036');
});
最后一块是协议缓冲区。默认情况下,google-protobuf
对 64 位 float
和 int
值使用 number
,这会导致溢出 Number.MAX_VALUE
或 253 - 1. 为避免这种情况,在 64 位字段上使用 jstype
注释,
message Uuid {
sfixed64 msb = 1 [jstype = JS_STRING];
sfixed64 lsb = 2 [jstype = JS_STRING];
}