This repository has been archived on 2026-03-06. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
openclaw-extensions/wecom/node_modules/win-guid/lib/guid.js
T

108 lines
3.5 KiB
JavaScript

/**
* Parse canonical GUID string (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
* into Windows / CFBF byte order.
*/
export function parseWindowsGuid(guid) {
let s = guid.trim();
// Keep validation readable and strict, avoid lowercasing allocations
if (s.length !== 36 ||
s[8] !== "-" ||
s[13] !== "-" ||
s[18] !== "-" ||
s[23] !== "-") {
throw new Error(`Invalid GUID format: ${guid}`);
}
let v;
const out = new Uint8Array(16);
// Data1: 8 hex, uint32 little-endian
v = parseInt(s.slice(0, 8), 16);
out[0] = v & 0xff;
out[1] = (v >>> 8) & 0xff;
out[2] = (v >>> 16) & 0xff;
out[3] = (v >>> 24) & 0xff;
// Data2: 4 hex, uint16 little-endian
v = parseInt(s.slice(9, 13), 16);
out[4] = v & 0xff;
out[5] = (v >>> 8) & 0xff;
// Data3: 4 hex, uint16 little-endian
v = parseInt(s.slice(14, 18), 16);
out[6] = v & 0xff;
out[7] = (v >>> 8) & 0xff;
// Data4: 4 hex, as-is (string order)
v = parseInt(s.slice(19, 23), 16);
out[8] = (v >>> 8) & 0xff;
out[9] = v & 0xff;
// Data5: 12 hex, 6 bytes, as-is (string order)
// Parse as two chunks to avoid any precision worries, keep it simple.
v = parseInt(s.slice(24, 32), 16); // 8 hex -> 4 bytes
out[10] = (v >>> 24) & 0xff;
out[11] = (v >>> 16) & 0xff;
out[12] = (v >>> 8) & 0xff;
out[13] = v & 0xff;
v = parseInt(s.slice(32, 36), 16); // 4 hex -> 2 bytes
out[14] = (v >>> 8) & 0xff;
out[15] = v & 0xff;
// Ensure all parsed parts were valid hex (parseInt can yield NaN)
for (let i = 0; i < 16; i++) {
if (!Number.isFinite(out[i])) {
throw new Error(`Invalid GUID format: ${guid}`);
}
}
// Also catch NaN early (more useful error locality)
// If any parseInt produced NaN, assignments above would have become 0,
// so instead validate hex characters directly with a lightweight check.
// (Keeps code small while staying strict.)
if (!/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(s)) {
throw new Error(`Invalid GUID format: ${guid}`);
}
return out;
}
export class Guid {
constructor(bytes) {
if (bytes.length !== 16)
throw new Error("GUID must be exactly 16 bytes");
this.bytes = bytes;
}
static fromString(guid) {
return new Guid(parseWindowsGuid(guid));
}
/**
* Convert Windows / CFBF byte order into canonical GUID string:
* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
*/
toString() {
const b = this.bytes;
const hx = (n) => n.toString(16).padStart(2, "0");
// Data1 (uint32 LE) -> big-endian text
const g1 = hx(b[3]) + hx(b[2]) + hx(b[1]) + hx(b[0]);
// Data2 (uint16 LE)
const g2 = hx(b[5]) + hx(b[4]);
// Data3 (uint16 LE)
const g3 = hx(b[7]) + hx(b[6]);
// Data4 (as-is)
const g4 = hx(b[8]) + hx(b[9]);
// Data5 (as-is)
const g5 = hx(b[10]) +
hx(b[11]) +
hx(b[12]) +
hx(b[13]) +
hx(b[14]) +
hx(b[15]);
return `${g1}-${g2}-${g3}-${g4}-${g5}`.toUpperCase();
}
/**
* Compare against a Uint8Array containing GUID bytes
* in Windows / CFBF layout.
*/
equals(buf, offset = 0) {
if (offset < 0 || buf.length - offset < 16)
return false;
const a = this.bytes;
for (let i = 0; i < 16; i++) {
if (buf[offset + i] !== a[i])
return false;
}
return true;
}
}