@ifc-lite/encoding 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,15 +40,15 @@ export declare function decodeIfcString(str: string): string;
40
40
  * a file no conformant reader parses as intended (e.g. a name like
41
41
  * `O'Brien`). A caller writing into a literal must double `'` itself, or use
42
42
  * `escapeStepString` from `@ifc-lite/data`, which handles the full
43
- * literal-context contract: doubling `'` and `\`, mapping control characters
44
- * to a space, and encoding non-ASCII —
43
+ * literal-context contract: doubling `'` and `\`, and encoding control
44
+ * characters and non-ASCII as directives —
45
45
  * per ISO 10303-21 6.3.3.4. The two functions do not produce the same output
46
46
  * for the same input; do not assume they agree. Sweeping U+0000..U+02FF, they
47
47
  * disagree on exactly two of the 95 printable ASCII characters: the
48
48
  * apostrophe (U+0027; doubled there, passed through here) and the reverse
49
49
  * solidus (U+005C; doubled there, `\X\5C` here). They also disagree on all 32
50
- * C0 controls AND on DEL (U+007F) -- a space there, `\X\HH` here, since
51
- * `escapeStepString` collapses `/[\x00-\x1F\x7F]/g` to a space -- and on all
50
+ * C0 controls AND on DEL (U+007F) -- `\X2\00HH\X0\` there, `\X\HH` here --
51
+ * and on all
52
52
  * 128 of U+0080..U+00FF (`\X2\HHHH\X0\` there, `\X\HH` here). That is 163
53
53
  * disagreements in all. Above U+00FF they agree on all 512.
54
54
  *
@@ -255,15 +255,15 @@ export function decodeIfcString(str) {
255
255
  * a file no conformant reader parses as intended (e.g. a name like
256
256
  * `O'Brien`). A caller writing into a literal must double `'` itself, or use
257
257
  * `escapeStepString` from `@ifc-lite/data`, which handles the full
258
- * literal-context contract: doubling `'` and `\`, mapping control characters
259
- * to a space, and encoding non-ASCII —
258
+ * literal-context contract: doubling `'` and `\`, and encoding control
259
+ * characters and non-ASCII as directives —
260
260
  * per ISO 10303-21 6.3.3.4. The two functions do not produce the same output
261
261
  * for the same input; do not assume they agree. Sweeping U+0000..U+02FF, they
262
262
  * disagree on exactly two of the 95 printable ASCII characters: the
263
263
  * apostrophe (U+0027; doubled there, passed through here) and the reverse
264
264
  * solidus (U+005C; doubled there, `\X\5C` here). They also disagree on all 32
265
- * C0 controls AND on DEL (U+007F) -- a space there, `\X\HH` here, since
266
- * `escapeStepString` collapses `/[\x00-\x1F\x7F]/g` to a space -- and on all
265
+ * C0 controls AND on DEL (U+007F) -- `\X2\00HH\X0\` there, `\X\HH` here --
266
+ * and on all
267
267
  * 128 of U+0080..U+00FF (`\X2\HHHH\X0\` there, `\X\HH` here). That is 163
268
268
  * disagreements in all. Above U+00FF they agree on all 512.
269
269
  *
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  export { decodeIfcString, encodeIfcString } from './ifc-string.js';
2
2
  export { decodeStepStringLiteral } from './step-string-literal.js';
3
+ export { isStepPageQuoteOperand, stepStringLiteralEnd } from './step-string-end.js';
4
+ export { splitStepTopLevel } from './step-top-level-split.js';
3
5
  export { uuidToIfcGuid, ifcGuidToUuid, generateIfcGuid, generateUuid, isValidIfcGuid, isValidUuid, } from './guid.js';
4
6
  export type { RandomSource } from './guid.js';
5
7
  export { uuidFromSeed } from './deterministic-uuid.js';
8
+ export { uuidV5 } from './uuid-v5.js';
6
9
  export { isWhollyNumeric } from './numeric-literal.js';
7
10
  export { parsePropertyValue } from './property-value.js';
8
11
  export type { ParsedPropertyValue } from './property-value.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -3,8 +3,11 @@
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
4
  export { decodeIfcString, encodeIfcString } from './ifc-string.js';
5
5
  export { decodeStepStringLiteral } from './step-string-literal.js';
6
+ export { isStepPageQuoteOperand, stepStringLiteralEnd } from './step-string-end.js';
7
+ export { splitStepTopLevel } from './step-top-level-split.js';
6
8
  export { uuidToIfcGuid, ifcGuidToUuid, generateIfcGuid, generateUuid, isValidIfcGuid, isValidUuid, } from './guid.js';
7
9
  export { uuidFromSeed } from './deterministic-uuid.js';
10
+ export { uuidV5 } from './uuid-v5.js';
8
11
  export { isWhollyNumeric } from './numeric-literal.js';
9
12
  export { parsePropertyValue } from './property-value.js';
10
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Where an ISO 10303-21 string literal ends, for every walker that splits,
3
+ * rewrites or scans STEP text (#7589).
4
+ *
5
+ * Inside a literal, `''` is an escaped quote and the PAGE directive `\S\` takes
6
+ * the next character as its operand, which may itself be an apostrophe:
7
+ * `'Para \S\' 5'` is one literal reading "Para § 5". The entity scanners learnt
8
+ * that in #7540; a walker that ends the literal at the operand misreads every
9
+ * later comma, paren and reference in the record. The PAGE test comes first,
10
+ * because `'5\S\''` is "5§" and closes at its last quote, and no other legal
11
+ * string unit can end in `\S\` right before a quote, so the lookback cannot
12
+ * misfire on a legal file. The byte-level twin is `isPageQuoteOperand` in
13
+ * `@ifc-lite/parser` (`step-lexing.ts`); the Rust one is
14
+ * `ifc_lite_core::step_encoding::step_string_literal_end`.
15
+ */
16
+ /** Whether the apostrophe at `pos` (inside a literal) is a `\S\` operand. */
17
+ export declare function isStepPageQuoteOperand(text: string, pos: number): boolean;
18
+ /**
19
+ * Index just past the apostrophe closing the literal whose opening apostrophe
20
+ * is at `open`, or `-1` when it never closes.
21
+ */
22
+ export declare function stepStringLiteralEnd(text: string, open: number): number;
23
+ //# sourceMappingURL=step-string-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-string-end.d.ts","sourceRoot":"","sources":["../src/step-string-end.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,6EAA6E;AAC7E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGzE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvE"}
@@ -0,0 +1,40 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Where an ISO 10303-21 string literal ends, for every walker that splits,
6
+ * rewrites or scans STEP text (#7589).
7
+ *
8
+ * Inside a literal, `''` is an escaped quote and the PAGE directive `\S\` takes
9
+ * the next character as its operand, which may itself be an apostrophe:
10
+ * `'Para \S\' 5'` is one literal reading "Para § 5". The entity scanners learnt
11
+ * that in #7540; a walker that ends the literal at the operand misreads every
12
+ * later comma, paren and reference in the record. The PAGE test comes first,
13
+ * because `'5\S\''` is "5§" and closes at its last quote, and no other legal
14
+ * string unit can end in `\S\` right before a quote, so the lookback cannot
15
+ * misfire on a legal file. The byte-level twin is `isPageQuoteOperand` in
16
+ * `@ifc-lite/parser` (`step-lexing.ts`); the Rust one is
17
+ * `ifc_lite_core::step_encoding::step_string_literal_end`.
18
+ */
19
+ /** Whether the apostrophe at `pos` (inside a literal) is a `\S\` operand. */
20
+ export function isStepPageQuoteOperand(text, pos) {
21
+ return pos >= 3 && text.charCodeAt(pos - 1) === 0x5c && text.charCodeAt(pos - 2) === 0x53
22
+ && text.charCodeAt(pos - 3) === 0x5c;
23
+ }
24
+ /**
25
+ * Index just past the apostrophe closing the literal whose opening apostrophe
26
+ * is at `open`, or `-1` when it never closes.
27
+ */
28
+ export function stepStringLiteralEnd(text, open) {
29
+ for (let p = text.indexOf("'", open + 1); p >= 0; p = text.indexOf("'", p + 1)) {
30
+ if (isStepPageQuoteOperand(text, p))
31
+ continue;
32
+ if (text.charCodeAt(p + 1) === 0x27) {
33
+ p++;
34
+ continue;
35
+ }
36
+ return p + 1;
37
+ }
38
+ return -1;
39
+ }
40
+ //# sourceMappingURL=step-string-end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-string-end.js","sourceRoot":"","sources":["../src/step-string-end.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;GAcG;AAEH,6EAA6E;AAC7E,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,GAAW;IAC9D,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI;WACpF,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,IAAY;IAC7D,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/E,IAAI,sBAAsB,CAAC,IAAI,EAAE,CAAC,CAAC;YAAE,SAAS;QAC9C,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,SAAS;QAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Split STEP parameter text at commas that are not inside parentheses or
3
+ * brackets, a string literal, or a `/* ... *\/` comment (#7785).
4
+ *
5
+ * The one TS splitter for text that is not a whole record. A literal ends by
6
+ * `stepStringLiteralEnd` (`''` and a `\S\'` PAGE operand stay inside, #7589),
7
+ * and a comment is skipped atomically, so a `,`, `(`, `)` or `'` in either is
8
+ * not structure. An unterminated literal or comment runs to the end of the
9
+ * text. Each comment collapses to one space so the tokens around it are not
10
+ * spliced (`5/* c *\/6` is not `56`). Items are trimmed; the last item is
11
+ * always returned, even when empty (callers decide whether a trailing empty
12
+ * item is a value).
13
+ */
14
+ export declare function splitStepTopLevel(text: string): string[];
15
+ //# sourceMappingURL=step-top-level-split.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-top-level-split.d.ts","sourceRoot":"","sources":["../src/step-top-level-split.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BxD"}
@@ -0,0 +1,50 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { stepStringLiteralEnd } from './step-string-end.js';
5
+ /**
6
+ * Split STEP parameter text at commas that are not inside parentheses or
7
+ * brackets, a string literal, or a `/* ... *\/` comment (#7785).
8
+ *
9
+ * The one TS splitter for text that is not a whole record. A literal ends by
10
+ * `stepStringLiteralEnd` (`''` and a `\S\'` PAGE operand stay inside, #7589),
11
+ * and a comment is skipped atomically, so a `,`, `(`, `)` or `'` in either is
12
+ * not structure. An unterminated literal or comment runs to the end of the
13
+ * text. Each comment collapses to one space so the tokens around it are not
14
+ * spliced (`5/* c *\/6` is not `56`). Items are trimmed; the last item is
15
+ * always returned, even when empty (callers decide whether a trailing empty
16
+ * item is a value).
17
+ */
18
+ export function splitStepTopLevel(text) {
19
+ const items = [];
20
+ let depth = 0;
21
+ let current = '';
22
+ for (let i = 0; i < text.length; i++) {
23
+ const ch = text[i];
24
+ if (ch === "'") {
25
+ const close = stepStringLiteralEnd(text, i);
26
+ const stop = close < 0 ? text.length : close;
27
+ current += text.slice(i, stop);
28
+ i = stop - 1;
29
+ }
30
+ else if (ch === '/' && text[i + 1] === '*') {
31
+ const close = text.indexOf('*/', i + 2);
32
+ current += ' ';
33
+ i = (close < 0 ? text.length : close + 2) - 1;
34
+ }
35
+ else if (ch === ',' && depth === 0) {
36
+ items.push(current.trim());
37
+ current = '';
38
+ }
39
+ else {
40
+ if (ch === '(' || ch === '[')
41
+ depth++;
42
+ else if (ch === ')' || ch === ']')
43
+ depth--;
44
+ current += ch;
45
+ }
46
+ }
47
+ items.push(current.trim());
48
+ return items;
49
+ }
50
+ //# sourceMappingURL=step-top-level-split.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-top-level-split.js","sourceRoot":"","sources":["../src/step-top-level-split.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YAC7C,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAC/B,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACxC,OAAO,IAAI,GAAG,CAAC;YACf,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3B,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;gBAAE,KAAK,EAAE,CAAC;iBACjC,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;gBAAE,KAAK,EAAE,CAAC;YAC3C,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Name-based UUID, version 5: the same `namespace` + `name` always yields the
3
+ * same lowercase 8-4-4-4-12 UUID. Compose with `uuidToIfcGuid` for a
4
+ * deterministic IFC GlobalId.
5
+ */
6
+ export declare function uuidV5(namespace: string, name: string): string;
7
+ //# sourceMappingURL=uuid-v5.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid-v5.d.ts","sourceRoot":"","sources":["../src/uuid-v5.ts"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAa9D"}
@@ -0,0 +1,82 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Name-based UUIDs, version 5 (RFC 9562 §5.5).
6
+ *
7
+ * Unlike {@link uuidFromSeed} (an ifc-lite-internal hash scheme), a v5 UUID is
8
+ * the standard, interoperable way to derive an identifier from a namespace +
9
+ * name: any conforming implementation, in any language, computes the same
10
+ * UUID. The viewer derives the GlobalId of the new piece of a split element
11
+ * this way (#6233), so the same split yields the same id everywhere.
12
+ */
13
+ import { isValidUuid } from './guid.js';
14
+ /**
15
+ * SHA-1 of `bytes`, synchronously. Only for name-based UUIDs, which fix SHA-1
16
+ * as their hash; it is NOT a security primitive here. Web Crypto's digest is
17
+ * async, and {@link uuidV5} is called inside synchronous edits.
18
+ */
19
+ function sha1(bytes) {
20
+ const bitLength = bytes.length * 8;
21
+ const padded = new Uint8Array(((bytes.length + 9 + 63) >> 6) << 6);
22
+ padded.set(bytes);
23
+ padded[bytes.length] = 0x80;
24
+ const view = new DataView(padded.buffer);
25
+ view.setUint32(padded.length - 8, Math.floor(bitLength / 0x100000000));
26
+ view.setUint32(padded.length - 4, bitLength >>> 0);
27
+ let h0 = 0x67452301, h1 = 0xefcdab89, h2 = 0x98badcfe, h3 = 0x10325476, h4 = 0xc3d2e1f0;
28
+ const w = new Uint32Array(80);
29
+ for (let block = 0; block < padded.length; block += 64) {
30
+ for (let i = 0; i < 16; i++)
31
+ w[i] = view.getUint32(block + i * 4);
32
+ for (let i = 16; i < 80; i++) {
33
+ const x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
34
+ w[i] = (x << 1) | (x >>> 31);
35
+ }
36
+ let a = h0, b = h1, c = h2, d = h3, e = h4;
37
+ for (let i = 0; i < 80; i++) {
38
+ const [f, k] = i < 20 ? [(b & c) | (~b & d), 0x5a827999]
39
+ : i < 40 ? [b ^ c ^ d, 0x6ed9eba1]
40
+ : i < 60 ? [(b & c) | (b & d) | (c & d), 0x8f1bbcdc]
41
+ : [b ^ c ^ d, 0xca62c1d6];
42
+ const t = (((a << 5) | (a >>> 27)) + f + e + k + w[i]) >>> 0;
43
+ e = d;
44
+ d = c;
45
+ c = (b << 30) | (b >>> 2);
46
+ b = a;
47
+ a = t;
48
+ }
49
+ h0 = (h0 + a) >>> 0;
50
+ h1 = (h1 + b) >>> 0;
51
+ h2 = (h2 + c) >>> 0;
52
+ h3 = (h3 + d) >>> 0;
53
+ h4 = (h4 + e) >>> 0;
54
+ }
55
+ const out = new Uint8Array(20);
56
+ const outView = new DataView(out.buffer);
57
+ [h0, h1, h2, h3, h4].forEach((h, i) => outView.setUint32(i * 4, h));
58
+ return out;
59
+ }
60
+ /**
61
+ * Name-based UUID, version 5: the same `namespace` + `name` always yields the
62
+ * same lowercase 8-4-4-4-12 UUID. Compose with `uuidToIfcGuid` for a
63
+ * deterministic IFC GlobalId.
64
+ */
65
+ export function uuidV5(namespace, name) {
66
+ if (!isValidUuid(namespace))
67
+ throw new Error(`Invalid namespace UUID: ${namespace}`);
68
+ const ns = namespace.replace(/-/g, '');
69
+ const nameBytes = new TextEncoder().encode(name);
70
+ const input = new Uint8Array(16 + nameBytes.length);
71
+ for (let i = 0; i < 16; i++)
72
+ input[i] = parseInt(ns.substring(i * 2, i * 2 + 2), 16);
73
+ input.set(nameBytes, 16);
74
+ const bytes = sha1(input).subarray(0, 16);
75
+ bytes[6] = (bytes[6] & 0x0f) | 0x50;
76
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
77
+ let hex = '';
78
+ for (const byte of bytes)
79
+ hex += byte.toString(16).padStart(2, '0');
80
+ return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-${hex.substring(12, 16)}-${hex.substring(16, 20)}-${hex.substring(20, 32)}`;
81
+ }
82
+ //# sourceMappingURL=uuid-v5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid-v5.js","sourceRoot":"","sources":["../src/uuid-v5.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/encoding",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "description": "IFC string encoding/decoding and property value parsing for IFC-Lite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "typescript": "^6.0.3",
17
- "vitest": "^4.1.11",
17
+ "vitest": "^5.0.3",
18
18
  "@ifc-lite/timing-ladder": "^0.1.0"
19
19
  },
20
20
  "license": "MPL-2.0",