Javascript 相当于 Java 的 UUID 类

问题描述 投票:0回答: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

这个相同的例子在另一个问题中被引用,它非常相似,所以这将是一个后续。虽然在 lsb, msb -> string 的相关问题中解决了,但我找不到反向问题的解决方案,string -> msb, lsb

原来的解决方案是

function toUuidString(lsb, msb) {
    return `${digits(msb >> 32n, 8n)}-${digits(msb >> 16n, 4n)}-${digits(
        msb,
        4n
    )}-${digits(lsb >> 48n, 4n)}-${digits(lsb, 12n)}`
}

function digits(value, ds) {
    const hi = 1n << (ds * 4n)

    return (hi | (value & (hi - 1n))).toString(16).slice(1)
}

现在我想要一个接受字符串并返回 msb 和 lsb 的函数。 沿着原始问题的路径,我发现了java源代码并尝试做等效的事情,这将是:

function fromString(name) {
    let components = name.split('-')

    if (components.length !== 5) {
        throw new Error(`Invalid UUID string: ${name}`)
    }

    for (let index = 0; index < 5; index++) {
        components[index] = `0x${components[index]}`
    }

    let mostSigBits = Number.parseInt(components[0], 16)
    mostSigBits <<= 16
    mostSigBits |= Number.parseInt(components[1], 16)
    mostSigBits <<= 16
    mostSigBits |= Number.parseInt(components[2], 16)

    let leastSigBits = Number.parseInt(components[3], 16)
    leastSigBits <<= 48
    leastSigBits |= Number.parseInt(components[4], 16)

    return {
        leastSigBits,
        mostSigBits,
    }
}

但是,当我尝试用类似的东西来测试它时:

const originalUuid = 'eb66c416-4739-465b-9af3-9dc33ed8eef9'
const parts = fromString(originalUuid)

const newUUid = toUuidString(
    BigInt(parts.leastSigBits),
    BigInt(parts.mostSigBits)
)

console.log('Original', originalUuid)
console.log('New', newUUid)

我没有获得等效的 uuid。它们有相同的部件,但缺少一些部件

Original eb66c416-4739-465b-9af3-9dc33ed8eef9
New 00000000-4739-465b-ffff-ffffbefbeef9

有什么想法出了什么问题吗?

javascript uuid bitwise-operators
2个回答
1
投票

最后我发现了问题——两段代码并不是严格等价的,java源代码声明mostSigBits和leastSigBits一样长,这在javascript中无法表示,所以我们需要使用BigInt。

总结我的问题和之前的问题,java UUID 操作的 javascript 等效项是:

字符串 -> MSB、LSB

function fromString(name) {
    let components = name.split('-')

    if (components.length !== 5) {
        throw new Error(`Invalid UUID string: ${name}`)
    }

    for (let index = 0; index < 5; index++) {
        components[index] = `0x${components[index]}`
    }

    let mostSigBits = BigInt(Number.parseInt(components[0], 16))
    mostSigBits <<= 16n
    mostSigBits |= BigInt(Number.parseInt(components[1], 16))
    mostSigBits <<= 16n
    mostSigBits |= BigInt(Number.parseInt(components[2], 16))

    let leastSigBits = BigInt(Number.parseInt(components[3], 16))
    leastSigBits <<= 48n
    leastSigBits |= BigInt(Number.parseInt(components[4], 16))

    return {
        leastSigBits,
        mostSigBits,
    }
}

msb、lsb -> 字符串(来自引用的问题)

function toUuidString(lsb, msb) {
    return `${digits(msb >> 32n, 8n)}-${digits(msb >> 16n, 4n)}-${digits(
        msb,
        4n
    )}-${digits(lsb >> 48n, 4n)}-${digits(lsb, 12n)}`
}

function digits(value, ds) {
    const hi = 1n << (ds * 4n)

    return (hi | (value & (hi - 1n))).toString(16).slice(1)
}


0
投票

Java对UUID生成的实现是在java.lang.Long::fastUUID处实现的。它对长值使用无符号右移操作,而JavaScript的BigInt没有

这里我实现了无符号位移右移操作,并复制了Java的fastUUID实现。

// fastUUID({msb: BigInt("-8432159880597844756"),
//           lsb: BigInt("-5548517530057857892")})
//
// Should be the same as:
//
// new java.util.UUID(-8432159880597844756, -5548517530057857892)
//
// which is 8afaf343-9baa-4cec-b2ff-b4b426dfa49c

© www.soinside.com 2019 - 2024. All rights reserved.