@fluidframework/id-compressor 2.118.0 → 3.0.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +34 -4
  2. package/README.md +10 -10
  3. package/{api-extractor.json → api-extractor/api-extractor-model.json} +1 -1
  4. package/dist/appendOnlySortedMap.js +6 -5
  5. package/dist/appendOnlySortedMap.js.map +1 -1
  6. package/dist/finalSpace.js +1 -3
  7. package/dist/finalSpace.js.map +1 -1
  8. package/dist/idCompressor.js +43 -37
  9. package/dist/idCompressor.js.map +1 -1
  10. package/dist/identifiers.js +1 -2
  11. package/dist/identifiers.js.map +1 -1
  12. package/dist/packageVersion.d.ts +1 -1
  13. package/dist/packageVersion.d.ts.map +1 -1
  14. package/dist/packageVersion.js +1 -1
  15. package/dist/packageVersion.js.map +1 -1
  16. package/dist/persistanceUtilities.js +6 -7
  17. package/dist/persistanceUtilities.js.map +1 -1
  18. package/dist/sessionSpaceNormalizer.js +3 -5
  19. package/dist/sessionSpaceNormalizer.js.map +1 -1
  20. package/dist/sessions.js +17 -15
  21. package/dist/sessions.js.map +1 -1
  22. package/dist/test/idCompressorTestUtilities.js +32 -15
  23. package/dist/test/idCompressorTestUtilities.js.map +1 -1
  24. package/dist/test/testCommon.js +7 -8
  25. package/dist/test/testCommon.js.map +1 -1
  26. package/dist/utilities.js +15 -16
  27. package/dist/utilities.js.map +1 -1
  28. package/lib/appendOnlySortedMap.js +6 -5
  29. package/lib/appendOnlySortedMap.js.map +1 -1
  30. package/lib/finalSpace.js +1 -3
  31. package/lib/finalSpace.js.map +1 -1
  32. package/lib/idCompressor.js +38 -32
  33. package/lib/idCompressor.js.map +1 -1
  34. package/lib/legacy.d.ts +1 -1
  35. package/lib/packageVersion.d.ts +1 -1
  36. package/lib/packageVersion.d.ts.map +1 -1
  37. package/lib/packageVersion.js +1 -1
  38. package/lib/packageVersion.js.map +1 -1
  39. package/lib/public.d.ts +1 -1
  40. package/lib/sessionSpaceNormalizer.js +3 -5
  41. package/lib/sessionSpaceNormalizer.js.map +1 -1
  42. package/lib/sessions.js +9 -7
  43. package/lib/sessions.js.map +1 -1
  44. package/lib/test/idCompressorTestUtilities.js +21 -4
  45. package/lib/test/idCompressorTestUtilities.js.map +1 -1
  46. package/package.json +33 -52
  47. package/src/packageVersion.ts +1 -1
  48. package/src/test/tsconfig.json +4 -1
  49. package/tsconfig.json +1 -1
  50. package/internal.d.ts +0 -11
  51. package/legacy.d.ts +0 -11
  52. /package/api-extractor/{api-extractor.current.json → api-extractor-report.current.json} +0 -0
  53. /package/api-extractor/{api-extractor.legacy.json → api-extractor-report.legacy.json} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"testCommon.js","sourceRoot":"","sources":["../../src/test/testCommon.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,kEAA+E;AAI/E,kDAIyB;AAgCzB;;;GAGG;AACH,SAAgB,SAAS,CAAC,EAAgB;IACzC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChB,CAAC;AAFD,8BAEC;AAED;;;GAGG;AACH,SAAgB,SAAS,CAAC,EAAgB;IACzC,OAAO,EAAE,GAAG,CAAC,CAAC;AACf,CAAC;AAFD,8BAEC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,eAAuB;IAClD,MAAM,EAAE,GAAG,eAA+B,CAAC;IAC3C,IAAA,iBAAM,EAAC,SAAS,CAAC,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACjD,OAAO,EAAE,CAAC;AACX,CAAC;AAJD,kCAIC;AAOD;;;;;;GAMG;AACH,SAAgB,WAAW,CAAO,GAAc,EAAE,GAAM,EAAE,YAA2B;IACpF,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAPD,kCAOC;AAED,SAAgB,iBAAiB,CAAC,QAAkB,EAAE,MAAc;IACnE,OAAO,IAAA,sCAAuB,EAAC,IAAA,gCAAiB,EAAC,IAAA,sCAAuB,EAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9F,CAAC;AAFD,8CAEC;AAaD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAgB,kBAAkB,CACjC,KAAoB,EACpB,OAAO,GAAG,6BAA6B;IAEvC,IAAA,iBAAM,EAAC,KAAK,KAAK,SAAS,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC;AACd,CAAC;AAND,gDAMC;AAED;;;;GAIG;AACH,SAAgB,IAAI,CAAC,OAAe;IACnC,IAAA,eAAQ,EAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAFD,oBAEC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, fail as coreFail } from \"@fluidframework/core-utils/internal\";\n\nimport type { IdCompressor } from \"../idCompressor.js\";\nimport type { OpSpaceCompressedId, SessionSpaceCompressedId, StableId } from \"../index.js\";\nimport {\n\tnumericUuidFromStableId,\n\toffsetNumericUuid,\n\tstableIdFromNumericUuid,\n} from \"../utilities.js\";\n\n/**\n * An identifier (v4 UUID) that has been shortened by a distributed compression algorithm.\n * Lacks a space (session/op), meaning its scope is the same as the space-specific ID from which it was derived.\n */\nexport type CompressedId =\n\t| SessionSpaceCompressedId\n\t| OpSpaceCompressedId\n\t| FinalCompressedId\n\t| LocalCompressedId;\n\n/**\n * A compressed ID that is stable and unique within the scope of network of compressors (i.e. a document).\n * It can only be used/decompressed in the context of the originating document.\n */\nexport type FinalCompressedId = number & {\n\treadonly FinalCompressedId: \"5d83d1e2-98b7-4e4e-a889-54c855cfa73d\";\n\n\t// Same brand as OpNormalizedCompressedId, as final IDs are always finally normalized\n\treadonly OpNormalized: \"9209432d-a959-4df7-b2ad-767ead4dbcae\";\n};\n\n/**\n * A compressed ID that is local to a session (can only be decompressed when paired with a SessionId).\n * Internally, it should not be persisted outside a scope annotated with the originating SessionId in order to be unambiguous.\n * If external persistence is needed (e.g. by a client), a StableId should be used instead.\n */\nexport type LocalCompressedId = number & {\n\treadonly LocalCompressedId: \"6fccb42f-e2a4-4243-bd29-f13d12b9c6d1\";\n} & SessionSpaceCompressedId; // Same brand as CompressedId, as local IDs are always locally normalized\n\n/**\n * Returns true if the supplied ID is a final ID.\n * @returns true if the supplied ID is a final ID.\n */\nexport function isFinalId(id: CompressedId): id is FinalCompressedId {\n\treturn id >= 0;\n}\n\n/**\n * Returns true if the supplied ID is a local ID.\n * @returns true if the supplied ID is a local ID.\n */\nexport function isLocalId(id: CompressedId): id is LocalCompressedId {\n\treturn id < 0;\n}\n\n/**\n * Turns a negative integer into a local compressed ID. For testing only.\n */\nexport function makeLocalId(negativeInteger: number): LocalCompressedId {\n\tconst id = negativeInteger as CompressedId;\n\tassert(isLocalId(id), \"Not a negative integer.\");\n\treturn id;\n}\n\n/**\n * Remove `readonly` from all fields.\n */\nexport type Mutable<T> = { -readonly [P in keyof T]: T[P] };\n\n/**\n * Retrieve a value from a map with the given key, or create a new entry if the key is not in the map.\n * @param map - The map to query/update\n * @param key - The key to lookup in the map\n * @param defaultValue - a function which returns a default value. This is called and used to set an initial value for the given key in the map if none exists\n * @returns either the existing value for the given key, or the newly-created value (the result of `defaultValue`)\n */\nexport function getOrCreate<K, V>(map: Map<K, V>, key: K, defaultValue: (key: K) => V): V {\n\tlet value = map.get(key);\n\tif (value === undefined) {\n\t\tvalue = defaultValue(key);\n\t\tmap.set(key, value);\n\t}\n\treturn value;\n}\n\nexport function incrementStableId(stableId: StableId, offset: number): StableId {\n\treturn stableIdFromNumericUuid(offsetNumericUuid(numericUuidFromStableId(stableId), offset));\n}\n\n/**\n * An immutable view of an `IdCompressor`\n */\nexport type ReadonlyIdCompressor = Omit<\n\tIdCompressor,\n\t| \"generateCompressedId\"\n\t| \"generateCompressedIdRange\"\n\t| \"takeNextCreationRange\"\n\t| \"finalizeCreationRange\"\n>;\n\n/**\n * Asserts a value is not undefined, and returns the value.\n * Use when violations are logic errors in the program.\n *\n * @remarks\n * When practical, prefer the pattern `x ?? fail('message')` over `assertNotUndefined(x, 'message')`.\n * Using `?? fail` allows for message formatting without incurring the cost of formatting the message\n * in the non failing case.\n *\n * Example:\n * ```typescript\n * x ?? fail(`x should exist for ${y}`)\n * ```\n *\n * Additionally the `?? fail` avoids an extra call/stack frame in the non failing case.\n *\n * Another pattern to prefer over `assertNotUndefined(x, 'message')` is `assert(x !== undefined)`.\n * This pattern is preferred because it is more general (same approach works with typeof, instance of,\n * comparison to other values etc.).\n *\n * @param value - Value to assert against is non undefined.\n * @param message - Message to be printed if assertion fails.\n */\nexport function assertNotUndefined<T>(\n\tvalue: T | undefined,\n\tmessage = \"value must not be undefined\",\n): T {\n\tassert(value !== undefined, message);\n\treturn value;\n}\n\n/**\n * Fails an assertion. Throws an Error that the assertion failed.\n * Use when violations are logic errors in the program.\n * @param message - Message to be printed if assertion fails.\n */\nexport function fail(message: string): never {\n\tcoreFail(message);\n}\n"]}
1
+ {"version":3,"file":"testCommon.js","sourceRoot":"","sources":["../../src/test/testCommon.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AA8CH,8BAEC;AAMD,8BAEC;AAKD,kCAIC;AAcD,kCAOC;AAED,8CAEC;AAoCD,gDAMC;AAOD,oBAEC;AA3ID,kEAA+E;AAI/E,kDAIyB;AAgCzB;;;GAGG;AACH,SAAgB,SAAS,CAAC,EAAgB;IACzC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAgB,SAAS,CAAC,EAAgB;IACzC,OAAO,EAAE,GAAG,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,eAAuB;IAClD,MAAM,EAAE,GAAG,eAA+B,CAAC;IAC3C,IAAA,iBAAM,EAAC,SAAS,CAAC,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACjD,OAAO,EAAE,CAAC;AACX,CAAC;AAOD;;;;;;GAMG;AACH,SAAgB,WAAW,CAAO,GAAc,EAAE,GAAM,EAAE,YAA2B;IACpF,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAgB,iBAAiB,CAAC,QAAkB,EAAE,MAAc;IACnE,OAAO,IAAA,sCAAuB,EAAC,IAAA,gCAAiB,EAAC,IAAA,sCAAuB,EAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9F,CAAC;AAaD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAgB,kBAAkB,CACjC,KAAoB,EACpB,OAAO,GAAG,6BAA6B;IAEvC,IAAA,iBAAM,EAAC,KAAK,KAAK,SAAS,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAgB,IAAI,CAAC,OAAe;IACnC,IAAA,eAAQ,EAAC,OAAO,CAAC,CAAC;AACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, fail as coreFail } from \"@fluidframework/core-utils/internal\";\n\nimport type { IdCompressor } from \"../idCompressor.js\";\nimport type { OpSpaceCompressedId, SessionSpaceCompressedId, StableId } from \"../index.js\";\nimport {\n\tnumericUuidFromStableId,\n\toffsetNumericUuid,\n\tstableIdFromNumericUuid,\n} from \"../utilities.js\";\n\n/**\n * An identifier (v4 UUID) that has been shortened by a distributed compression algorithm.\n * Lacks a space (session/op), meaning its scope is the same as the space-specific ID from which it was derived.\n */\nexport type CompressedId =\n\t| SessionSpaceCompressedId\n\t| OpSpaceCompressedId\n\t| FinalCompressedId\n\t| LocalCompressedId;\n\n/**\n * A compressed ID that is stable and unique within the scope of network of compressors (i.e. a document).\n * It can only be used/decompressed in the context of the originating document.\n */\nexport type FinalCompressedId = number & {\n\treadonly FinalCompressedId: \"5d83d1e2-98b7-4e4e-a889-54c855cfa73d\";\n\n\t// Same brand as OpNormalizedCompressedId, as final IDs are always finally normalized\n\treadonly OpNormalized: \"9209432d-a959-4df7-b2ad-767ead4dbcae\";\n};\n\n/**\n * A compressed ID that is local to a session (can only be decompressed when paired with a SessionId).\n * Internally, it should not be persisted outside a scope annotated with the originating SessionId in order to be unambiguous.\n * If external persistence is needed (e.g. by a client), a StableId should be used instead.\n */\nexport type LocalCompressedId = number & {\n\treadonly LocalCompressedId: \"6fccb42f-e2a4-4243-bd29-f13d12b9c6d1\";\n} & SessionSpaceCompressedId; // Same brand as CompressedId, as local IDs are always locally normalized\n\n/**\n * Returns true if the supplied ID is a final ID.\n * @returns true if the supplied ID is a final ID.\n */\nexport function isFinalId(id: CompressedId): id is FinalCompressedId {\n\treturn id >= 0;\n}\n\n/**\n * Returns true if the supplied ID is a local ID.\n * @returns true if the supplied ID is a local ID.\n */\nexport function isLocalId(id: CompressedId): id is LocalCompressedId {\n\treturn id < 0;\n}\n\n/**\n * Turns a negative integer into a local compressed ID. For testing only.\n */\nexport function makeLocalId(negativeInteger: number): LocalCompressedId {\n\tconst id = negativeInteger as CompressedId;\n\tassert(isLocalId(id), \"Not a negative integer.\");\n\treturn id;\n}\n\n/**\n * Remove `readonly` from all fields.\n */\nexport type Mutable<T> = { -readonly [P in keyof T]: T[P] };\n\n/**\n * Retrieve a value from a map with the given key, or create a new entry if the key is not in the map.\n * @param map - The map to query/update\n * @param key - The key to lookup in the map\n * @param defaultValue - a function which returns a default value. This is called and used to set an initial value for the given key in the map if none exists\n * @returns either the existing value for the given key, or the newly-created value (the result of `defaultValue`)\n */\nexport function getOrCreate<K, V>(map: Map<K, V>, key: K, defaultValue: (key: K) => V): V {\n\tlet value = map.get(key);\n\tif (value === undefined) {\n\t\tvalue = defaultValue(key);\n\t\tmap.set(key, value);\n\t}\n\treturn value;\n}\n\nexport function incrementStableId(stableId: StableId, offset: number): StableId {\n\treturn stableIdFromNumericUuid(offsetNumericUuid(numericUuidFromStableId(stableId), offset));\n}\n\n/**\n * An immutable view of an `IdCompressor`\n */\nexport type ReadonlyIdCompressor = Omit<\n\tIdCompressor,\n\t| \"generateCompressedId\"\n\t| \"generateCompressedIdRange\"\n\t| \"takeNextCreationRange\"\n\t| \"finalizeCreationRange\"\n>;\n\n/**\n * Asserts a value is not undefined, and returns the value.\n * Use when violations are logic errors in the program.\n *\n * @remarks\n * When practical, prefer the pattern `x ?? fail('message')` over `assertNotUndefined(x, 'message')`.\n * Using `?? fail` allows for message formatting without incurring the cost of formatting the message\n * in the non failing case.\n *\n * Example:\n * ```typescript\n * x ?? fail(`x should exist for ${y}`)\n * ```\n *\n * Additionally the `?? fail` avoids an extra call/stack frame in the non failing case.\n *\n * Another pattern to prefer over `assertNotUndefined(x, 'message')` is `assert(x !== undefined)`.\n * This pattern is preferred because it is more general (same approach works with typeof, instance of,\n * comparison to other values etc.).\n *\n * @param value - Value to assert against is non undefined.\n * @param message - Message to be printed if assertion fails.\n */\nexport function assertNotUndefined<T>(\n\tvalue: T | undefined,\n\tmessage = \"value must not be undefined\",\n): T {\n\tassert(value !== undefined, message);\n\treturn value;\n}\n\n/**\n * Fails an assertion. Throws an Error that the assertion failed.\n * Use when violations are logic errors in the program.\n * @param message - Message to be printed if assertion fails.\n */\nexport function fail(message: string): never {\n\tcoreFail(message);\n}\n"]}
package/dist/utilities.js CHANGED
@@ -4,7 +4,21 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.addNumericUuids = exports.subtractNumericUuids = exports.offsetNumericUuid = exports.stableIdFromNumericUuid = exports.numericUuidFromStableId = exports.localIdFromGenCount = exports.genCountFromLocalId = exports.compareBigints = exports.compareStrings = exports.compareFiniteNumbers = exports.isStableId = exports.generateStableId = exports.assertIsSessionId = exports.assertIsStableId = exports.createSessionId = void 0;
7
+ exports.createSessionId = createSessionId;
8
+ exports.assertIsStableId = assertIsStableId;
9
+ exports.assertIsSessionId = assertIsSessionId;
10
+ exports.generateStableId = generateStableId;
11
+ exports.isStableId = isStableId;
12
+ exports.compareFiniteNumbers = compareFiniteNumbers;
13
+ exports.compareStrings = compareStrings;
14
+ exports.compareBigints = compareBigints;
15
+ exports.genCountFromLocalId = genCountFromLocalId;
16
+ exports.localIdFromGenCount = localIdFromGenCount;
17
+ exports.numericUuidFromStableId = numericUuidFromStableId;
18
+ exports.stableIdFromNumericUuid = stableIdFromNumericUuid;
19
+ exports.offsetNumericUuid = offsetNumericUuid;
20
+ exports.subtractNumericUuids = subtractNumericUuids;
21
+ exports.addNumericUuids = addNumericUuids;
8
22
  /* eslint-disable no-bitwise */
9
23
  const internal_1 = require("@fluidframework/core-utils/internal");
10
24
  const uuid_1 = require("uuid");
@@ -21,7 +35,6 @@ function isHexadecimalCharacter(charCode) {
21
35
  function createSessionId() {
22
36
  return assertIsStableId((0, uuid_1.v4)());
23
37
  }
24
- exports.createSessionId = createSessionId;
25
38
  /**
26
39
  * Asserts that the given string is a stable ID.
27
40
  * @internal
@@ -30,7 +43,6 @@ function assertIsStableId(stableId) {
30
43
  (0, internal_1.assert)(isStableId(stableId), 0x4a3 /* Expected a StableId */);
31
44
  return stableId;
32
45
  }
33
- exports.assertIsStableId = assertIsStableId;
34
46
  /**
35
47
  * Asserts that the given string is a stable ID.
36
48
  */
@@ -38,7 +50,6 @@ function assertIsSessionId(stableId) {
38
50
  assertIsStableId(stableId);
39
51
  return stableId;
40
52
  }
41
- exports.assertIsSessionId = assertIsSessionId;
42
53
  /**
43
54
  * Generate a random stable ID
44
55
  * @internal
@@ -46,7 +57,6 @@ exports.assertIsSessionId = assertIsSessionId;
46
57
  function generateStableId() {
47
58
  return assertIsStableId((0, uuid_1.v4)());
48
59
  }
49
- exports.generateStableId = generateStableId;
50
60
  /**
51
61
  * Returns true iff the given string is a valid Version 4, variant 2 UUID
52
62
  * 'xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx'
@@ -92,7 +102,6 @@ function isStableId(str) {
92
102
  }
93
103
  return true;
94
104
  }
95
- exports.isStableId = isStableId;
96
105
  /**
97
106
  * A numeric comparator used for sorting in ascending order.
98
107
  *
@@ -101,30 +110,25 @@ exports.isStableId = isStableId;
101
110
  function compareFiniteNumbers(a, b) {
102
111
  return a - b;
103
112
  }
104
- exports.compareFiniteNumbers = compareFiniteNumbers;
105
113
  /**
106
114
  * Compares strings lexically to form a strict partial ordering.
107
115
  */
108
116
  function compareStrings(a, b) {
109
117
  return a > b ? 1 : a === b ? 0 : -1;
110
118
  }
111
- exports.compareStrings = compareStrings;
112
119
  /**
113
120
  * Compares bigints to form a strict partial ordering.
114
121
  */
115
122
  function compareBigints(a, b) {
116
123
  return a > b ? 1 : a === b ? 0 : -1;
117
124
  }
118
- exports.compareBigints = compareBigints;
119
125
  function genCountFromLocalId(localId) {
120
126
  // eslint-disable-next-line @typescript-eslint/no-unsafe-unary-minus
121
127
  return -localId;
122
128
  }
123
- exports.genCountFromLocalId = genCountFromLocalId;
124
129
  function localIdFromGenCount(genCount) {
125
130
  return -genCount;
126
131
  }
127
- exports.localIdFromGenCount = localIdFromGenCount;
128
132
  // xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
129
133
  const versionMask = 0x4n << (19n * 4n); // Version 4
130
134
  const variantMask = 0x8n << (15n * 4n); // Variant RFC4122 (1 0 x x)
@@ -147,7 +151,6 @@ function numericUuidFromStableId(stableId) {
147
151
  const id = upperMaskedPlaced | middieBittiesMaskedPlaced | lowerMasked;
148
152
  return id;
149
153
  }
150
- exports.numericUuidFromStableId = numericUuidFromStableId;
151
154
  function stableIdFromNumericUuid(numericUuid) {
152
155
  // bitwise reverse transform
153
156
  const upperMasked = (numericUuid & strippedUpperMask) << 6n;
@@ -158,17 +161,13 @@ function stableIdFromNumericUuid(numericUuid) {
158
161
  const uuidString = uuidU128.toString(16).padStart(32, "0");
159
162
  return `${uuidString.slice(0, 8)}-${uuidString.slice(8, 12)}-${uuidString.slice(12, 16)}-${uuidString.slice(16, 20)}-${uuidString.slice(20, 32)}`;
160
163
  }
161
- exports.stableIdFromNumericUuid = stableIdFromNumericUuid;
162
164
  function offsetNumericUuid(numericUuid, offset) {
163
165
  return (numericUuid + BigInt(offset));
164
166
  }
165
- exports.offsetNumericUuid = offsetNumericUuid;
166
167
  function subtractNumericUuids(a, b) {
167
168
  return (a - b);
168
169
  }
169
- exports.subtractNumericUuids = subtractNumericUuids;
170
170
  function addNumericUuids(a, b) {
171
171
  return (a + b);
172
172
  }
173
- exports.addNumericUuids = addNumericUuids;
174
173
  //# sourceMappingURL=utilities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable no-bitwise */\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { v4 } from \"uuid\";\n\nimport type { LocalCompressedId, NumericUuid } from \"./identifiers.js\";\nimport type { SessionId, StableId } from \"./types/index.js\";\n\nconst hexadecimalCharCodes = [...\"09afAF\"].map((c) => c.codePointAt(0)) as [\n\tzero: number,\n\tnine: number,\n\ta: number,\n\tf: number,\n\tA: number,\n\tF: number,\n];\n\nfunction isHexadecimalCharacter(charCode: number): boolean {\n\treturn (\n\t\t(charCode >= hexadecimalCharCodes[0] && charCode <= hexadecimalCharCodes[1]) ||\n\t\t(charCode >= hexadecimalCharCodes[2] && charCode <= hexadecimalCharCodes[3]) ||\n\t\t(charCode >= hexadecimalCharCodes[4] && charCode <= hexadecimalCharCodes[5])\n\t);\n}\n\n/**\n * Generate a random session ID\n * @legacy @beta\n */\nexport function createSessionId(): SessionId {\n\treturn assertIsStableId(v4()) as SessionId;\n}\n\n/**\n * Asserts that the given string is a stable ID.\n * @internal\n */\nexport function assertIsStableId(stableId: string): StableId {\n\tassert(isStableId(stableId), 0x4a3 /* Expected a StableId */);\n\treturn stableId;\n}\n\n/**\n * Asserts that the given string is a stable ID.\n */\nexport function assertIsSessionId(stableId: string): SessionId {\n\tassertIsStableId(stableId);\n\treturn stableId as SessionId;\n}\n\n/**\n * Generate a random stable ID\n * @internal\n */\nexport function generateStableId(): StableId {\n\treturn assertIsStableId(v4());\n}\n\n/**\n * Returns true iff the given string is a valid Version 4, variant 2 UUID\n * 'xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx'\n * @internal\n */\nexport function isStableId(str: string): str is StableId {\n\tif (str.length !== 36) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\tswitch (i) {\n\t\t\tcase 8:\n\t\t\tcase 13:\n\t\t\tcase 18:\n\t\t\tcase 23: {\n\t\t\t\tif (str.charAt(i) !== \"-\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 14: {\n\t\t\t\tif (str.charAt(i) !== \"4\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 19: {\n\t\t\t\tconst char = str.charAt(i);\n\t\t\t\tif (char !== \"8\" && char !== \"9\" && char !== \"a\" && char !== \"b\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst codePoint = str.codePointAt(i);\n\t\t\t\tassert(codePoint !== undefined, 0xaaf /* Unexpected undefined code point */);\n\t\t\t\tif (!isHexadecimalCharacter(codePoint)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * A numeric comparator used for sorting in ascending order.\n *\n * Handles +/-0 like Map: -0 is equal to +0.\n */\nexport function compareFiniteNumbers<T extends number>(a: T, b: T): number {\n\treturn a - b;\n}\n\n/**\n * Compares strings lexically to form a strict partial ordering.\n */\nexport function compareStrings<T extends string>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\n/**\n * Compares bigints to form a strict partial ordering.\n */\nexport function compareBigints<T extends bigint>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\nexport function genCountFromLocalId(localId: LocalCompressedId): number {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-unary-minus\n\treturn -localId;\n}\n\nexport function localIdFromGenCount(genCount: number): LocalCompressedId {\n\treturn -genCount as LocalCompressedId;\n}\n\n// xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx\nconst versionMask = 0x4n << (19n * 4n); // Version 4\nconst variantMask = 0x8n << (15n * 4n); // Variant RFC4122 (1 0 x x)\nconst upperMask = 0xffffffffffffn << (20n * 4n);\n// Upper mask when version/variant bits are removed\nconst strippedUpperMask = upperMask >> 6n;\nconst middieBittiesMask = 0xfffn << (16n * 4n);\n// Middie mask when version/variant bits are removed\nconst strippedMiddieBittiesMask = middieBittiesMask >> 2n;\n// Note: leading character should be 3 to mask at 0011\n// The more-significant half of the N nibble is used to denote the variant (10xx)\nconst lowerMask = 0x3fffffffffffffffn;\n\nexport function numericUuidFromStableId(stableId: StableId): NumericUuid {\n\tconst uuidU128 = BigInt(`0x${stableId.replace(/-/g, \"\")}`);\n\tconst upperMasked = uuidU128 & upperMask;\n\tconst middieBittiesMasked = uuidU128 & middieBittiesMask;\n\tconst lowerMasked = uuidU128 & lowerMask;\n\n\tconst upperMaskedPlaced = upperMasked >> 6n;\n\tconst middieBittiesMaskedPlaced = middieBittiesMasked >> 2n;\n\n\tconst id = upperMaskedPlaced | middieBittiesMaskedPlaced | lowerMasked;\n\treturn id as NumericUuid;\n}\n\nexport function stableIdFromNumericUuid(numericUuid: NumericUuid): StableId {\n\t// bitwise reverse transform\n\tconst upperMasked = (numericUuid & strippedUpperMask) << 6n;\n\tconst middieBittiesMasked = (numericUuid & strippedMiddieBittiesMask) << 2n;\n\tconst lowerMasked = numericUuid & lowerMask;\n\tconst uuidU128 = upperMasked | versionMask | middieBittiesMasked | variantMask | lowerMasked;\n\t// Pad to 32 characters, inserting leading zeroes if needed\n\tconst uuidString = uuidU128.toString(16).padStart(32, \"0\");\n\treturn `${uuidString.slice(0, 8)}-${uuidString.slice(8, 12)}-${uuidString.slice(\n\t\t12,\n\t\t16,\n\t)}-${uuidString.slice(16, 20)}-${uuidString.slice(20, 32)}` as StableId;\n}\n\nexport function offsetNumericUuid(numericUuid: NumericUuid, offset: number): NumericUuid {\n\treturn (numericUuid + BigInt(offset)) as NumericUuid;\n}\n\nexport function subtractNumericUuids(a: NumericUuid, b: NumericUuid): NumericUuid {\n\treturn (a - b) as NumericUuid;\n}\n\nexport function addNumericUuids(a: NumericUuid, b: NumericUuid): NumericUuid {\n\treturn (a + b) as NumericUuid;\n}\n"]}
1
+ {"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable no-bitwise */\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { v4 } from \"uuid\";\n\nimport type { LocalCompressedId, NumericUuid } from \"./identifiers.js\";\nimport type { SessionId, StableId } from \"./types/index.js\";\n\nconst hexadecimalCharCodes = [...\"09afAF\"].map((c) => c.codePointAt(0)) as [\n\tzero: number,\n\tnine: number,\n\ta: number,\n\tf: number,\n\tA: number,\n\tF: number,\n];\n\nfunction isHexadecimalCharacter(charCode: number): boolean {\n\treturn (\n\t\t(charCode >= hexadecimalCharCodes[0] && charCode <= hexadecimalCharCodes[1]) ||\n\t\t(charCode >= hexadecimalCharCodes[2] && charCode <= hexadecimalCharCodes[3]) ||\n\t\t(charCode >= hexadecimalCharCodes[4] && charCode <= hexadecimalCharCodes[5])\n\t);\n}\n\n/**\n * Generate a random session ID\n * @legacy @beta\n */\nexport function createSessionId(): SessionId {\n\treturn assertIsStableId(v4()) as SessionId;\n}\n\n/**\n * Asserts that the given string is a stable ID.\n * @internal\n */\nexport function assertIsStableId(stableId: string): StableId {\n\tassert(isStableId(stableId), 0x4a3 /* Expected a StableId */);\n\treturn stableId;\n}\n\n/**\n * Asserts that the given string is a stable ID.\n */\nexport function assertIsSessionId(stableId: string): SessionId {\n\tassertIsStableId(stableId);\n\treturn stableId as SessionId;\n}\n\n/**\n * Generate a random stable ID\n * @internal\n */\nexport function generateStableId(): StableId {\n\treturn assertIsStableId(v4());\n}\n\n/**\n * Returns true iff the given string is a valid Version 4, variant 2 UUID\n * 'xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx'\n * @internal\n */\nexport function isStableId(str: string): str is StableId {\n\tif (str.length !== 36) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\tswitch (i) {\n\t\t\tcase 8:\n\t\t\tcase 13:\n\t\t\tcase 18:\n\t\t\tcase 23: {\n\t\t\t\tif (str.charAt(i) !== \"-\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 14: {\n\t\t\t\tif (str.charAt(i) !== \"4\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 19: {\n\t\t\t\tconst char = str.charAt(i);\n\t\t\t\tif (char !== \"8\" && char !== \"9\" && char !== \"a\" && char !== \"b\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst codePoint = str.codePointAt(i);\n\t\t\t\tassert(codePoint !== undefined, 0xaaf /* Unexpected undefined code point */);\n\t\t\t\tif (!isHexadecimalCharacter(codePoint)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * A numeric comparator used for sorting in ascending order.\n *\n * Handles +/-0 like Map: -0 is equal to +0.\n */\nexport function compareFiniteNumbers<T extends number>(a: T, b: T): number {\n\treturn a - b;\n}\n\n/**\n * Compares strings lexically to form a strict partial ordering.\n */\nexport function compareStrings<T extends string>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\n/**\n * Compares bigints to form a strict partial ordering.\n */\nexport function compareBigints<T extends bigint>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\nexport function genCountFromLocalId(localId: LocalCompressedId): number {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-unary-minus\n\treturn -localId;\n}\n\nexport function localIdFromGenCount(genCount: number): LocalCompressedId {\n\treturn -genCount as LocalCompressedId;\n}\n\n// xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx\nconst versionMask = 0x4n << (19n * 4n); // Version 4\nconst variantMask = 0x8n << (15n * 4n); // Variant RFC4122 (1 0 x x)\nconst upperMask = 0xffffffffffffn << (20n * 4n);\n// Upper mask when version/variant bits are removed\nconst strippedUpperMask = upperMask >> 6n;\nconst middieBittiesMask = 0xfffn << (16n * 4n);\n// Middie mask when version/variant bits are removed\nconst strippedMiddieBittiesMask = middieBittiesMask >> 2n;\n// Note: leading character should be 3 to mask at 0011\n// The more-significant half of the N nibble is used to denote the variant (10xx)\nconst lowerMask = 0x3fffffffffffffffn;\n\nexport function numericUuidFromStableId(stableId: StableId): NumericUuid {\n\tconst uuidU128 = BigInt(`0x${stableId.replace(/-/g, \"\")}`);\n\tconst upperMasked = uuidU128 & upperMask;\n\tconst middieBittiesMasked = uuidU128 & middieBittiesMask;\n\tconst lowerMasked = uuidU128 & lowerMask;\n\n\tconst upperMaskedPlaced = upperMasked >> 6n;\n\tconst middieBittiesMaskedPlaced = middieBittiesMasked >> 2n;\n\n\tconst id = upperMaskedPlaced | middieBittiesMaskedPlaced | lowerMasked;\n\treturn id as NumericUuid;\n}\n\nexport function stableIdFromNumericUuid(numericUuid: NumericUuid): StableId {\n\t// bitwise reverse transform\n\tconst upperMasked = (numericUuid & strippedUpperMask) << 6n;\n\tconst middieBittiesMasked = (numericUuid & strippedMiddieBittiesMask) << 2n;\n\tconst lowerMasked = numericUuid & lowerMask;\n\tconst uuidU128 = upperMasked | versionMask | middieBittiesMasked | variantMask | lowerMasked;\n\t// Pad to 32 characters, inserting leading zeroes if needed\n\tconst uuidString = uuidU128.toString(16).padStart(32, \"0\");\n\treturn `${uuidString.slice(0, 8)}-${uuidString.slice(8, 12)}-${uuidString.slice(\n\t\t12,\n\t\t16,\n\t)}-${uuidString.slice(16, 20)}-${uuidString.slice(20, 32)}` as StableId;\n}\n\nexport function offsetNumericUuid(numericUuid: NumericUuid, offset: number): NumericUuid {\n\treturn (numericUuid + BigInt(offset)) as NumericUuid;\n}\n\nexport function subtractNumericUuids(a: NumericUuid, b: NumericUuid): NumericUuid {\n\treturn (a - b) as NumericUuid;\n}\n\nexport function addNumericUuids(a: NumericUuid, b: NumericUuid): NumericUuid {\n\treturn (a + b) as NumericUuid;\n}\n"]}
@@ -9,12 +9,13 @@ import { assert } from "@fluidframework/core-utils/internal";
9
9
  * Supports appending and searching.
10
10
  */
11
11
  export class AppendOnlySortedMap {
12
+ comparator;
13
+ elements = [];
12
14
  /**
13
15
  * @param comparator - a comparator for keys
14
16
  */
15
17
  constructor(comparator) {
16
18
  this.comparator = comparator;
17
- this.elements = [];
18
19
  }
19
20
  /**
20
21
  * Gets the size of the map.
@@ -295,6 +296,10 @@ export class AppendOnlySortedMap {
295
296
  }
296
297
  return keyIndex;
297
298
  }
299
+ /**
300
+ * The value xor'd with the result index when a search fails.
301
+ */
302
+ static failureXor = -1;
298
303
  /**
299
304
  * Performs a binary search on the sorted array.
300
305
  * @returns the index of the key for `search`, or (if not present) the index it would have been inserted into xor'd
@@ -325,8 +330,4 @@ export class AppendOnlySortedMap {
325
330
  return (mid * 2) ^ AppendOnlySortedMap.failureXor;
326
331
  }
327
332
  }
328
- /**
329
- * The value xor'd with the result index when a search fails.
330
- */
331
- AppendOnlySortedMap.failureXor = -1;
332
333
  //# sourceMappingURL=appendOnlySortedMap.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"appendOnlySortedMap.js","sourceRoot":"","sources":["../src/appendOnlySortedMap.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable no-bitwise */\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\n/**\n * A map in which entries are always added in key-sorted order.\n * Supports appending and searching.\n */\nexport class AppendOnlySortedMap<K, V> {\n\tprotected readonly elements: (K | V)[] = [];\n\n\t/**\n\t * @param comparator - a comparator for keys\n\t */\n\tpublic constructor(protected readonly comparator: (a: K, b: K) => number) {}\n\n\t/**\n\t * Gets the size of the map.\n\t * @returns the number of entries in this map\n\t */\n\tpublic get size(): number {\n\t\treturn this.elements.length / 2;\n\t}\n\n\t/**\n\t * Gets the min key in the map.\n\t * @returns the min key in the map.\n\t */\n\tpublic minKey(): K | undefined {\n\t\treturn this.elements[0] as K | undefined;\n\t}\n\n\t/**\n\t * Gets the max key in the map.\n\t * @returns the max key in the map.\n\t */\n\tpublic maxKey(): K | undefined {\n\t\treturn this.elements[this.elements.length - 2] as K | undefined;\n\t}\n\n\t/**\n\t * Gets the min value in the map.\n\t * @returns the min value in the map.\n\t */\n\tpublic minValue(): V | undefined {\n\t\treturn this.elements[1] as V | undefined;\n\t}\n\n\t/**\n\t * Gets the max value in the map.\n\t * @returns the max value in the map.\n\t */\n\tpublic maxValue(): V | undefined {\n\t\treturn this.elements[this.elements.length - 1] as V | undefined;\n\t}\n\n\t/**\n\t * Gets the first key/value pair in the map.\n\t * @returns the first pair if it exists, or undefined otherwise.\n\t */\n\tpublic first(): [K, V] | undefined {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [elements[0] as K, elements[1] as V];\n\t}\n\n\t/**\n\t * Gets the last key/value pair in the map.\n\t * @returns the last pair if it exists, or undefined otherwise.\n\t */\n\tpublic last(): [K, V] | undefined {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst lastKeyIndex = length - 2;\n\t\treturn [elements[lastKeyIndex] as K, elements[lastKeyIndex + 1] as V];\n\t}\n\n\t/**\n\t * Gets the entry at the specified index.\n\t * @param index - the entry index\n\t * @returns the key/value pair if it exists, or undefined otherwise.\n\t */\n\tpublic getAtIndex(index: number): [K, V] | undefined {\n\t\tconst realIndex = index * 2;\n\t\tconst { elements } = this;\n\t\tif (realIndex < 0 || realIndex > elements.length - 1) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [elements[realIndex] as K, elements[realIndex + 1] as V];\n\t}\n\n\t/**\n\t * Gets the entries in the map.\n\t * @returns an iterable of the entries in the map.\n\t */\n\tpublic *entries(): IterableIterator<readonly [K, V]> {\n\t\tconst { elements } = this;\n\t\tfor (let i = 0; i < elements.length; i += 2) {\n\t\t\tyield [elements[i] as K, elements[i + 1] as V];\n\t\t}\n\t}\n\n\t/**\n\t * Gets the keys in the map.\n\t * @returns an iterable of the keys in the map.\n\t */\n\tpublic *keys(): IterableIterator<K> {\n\t\tconst { elements } = this;\n\t\tfor (let i = 0; i < elements.length; i += 2) {\n\t\t\tyield elements[i] as K;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the values in the map.\n\t * @returns an iterable of the values in the map.\n\t */\n\tpublic *values(): IterableIterator<V> {\n\t\tconst { elements } = this;\n\t\tfor (let i = 0; i < elements.length; i += 2) {\n\t\t\tyield elements[i + 1] as V;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the entries in the map, reversed.\n\t * @returns an iterable of the entries in the map, reversed.\n\t */\n\tpublic *entriesReversed(): IterableIterator<readonly [K, V]> {\n\t\tconst { elements } = this;\n\t\tfor (let i = elements.length - 2; i >= 0; i -= 2) {\n\t\t\tyield [elements[i] as K, elements[i + 1] as V];\n\t\t}\n\t}\n\n\t/**\n\t * Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.\n\t * @param key - the key to add\n\t * @param value - the value to add\n\t */\n\tpublic append(key: K, value: V): void {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length !== 0 && this.comparator(key, this.maxKey() as K) <= 0) {\n\t\t\tthrow new Error(\"Inserted key must be > all others in the map.\");\n\t\t}\n\t\telements.push(key, value);\n\t}\n\n\t/**\n\t * Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.\n\t * 'key' must be greater than all other keys in the map.\n\t * @param key - the key to set\n\t * @param value - the value to set\n\t */\n\tpublic replaceLast(key: K, value: V): void {\n\t\tconst { elements, comparator } = this;\n\t\tconst { length } = elements;\n\t\tif (length !== 0) {\n\t\t\telements.pop();\n\t\t\telements.pop();\n\t\t\tif (comparator(key, this.maxKey() as K) <= 0) {\n\t\t\t\tthrow new Error(\"Inserted key must be > all others in the map.\");\n\t\t\t}\n\t\t}\n\t\telements.push(key, value);\n\t}\n\n\t/**\n\t * Gets the value associated with a given key.\n\t * @param key - the key to lookup\n\t * @returns the value if it exists, or undefined otherwise.\n\t */\n\tpublic get(key: K): V | undefined {\n\t\tconst index = AppendOnlySortedMap.keyIndexOf(this.elements, key, this.comparator);\n\t\tif (index < 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.elements[index + 1] as V;\n\t}\n\n\t/**\n\t * Gets the pair associated with the given key or the next smaller key.\n\t * @param key - the key to lookup\n\t * @returns the pair if it exists, or undefined otherwise.\n\t */\n\tpublic getPairOrNextLower(key: K): readonly [K, V] | undefined {\n\t\treturn this.getPairOrNextLowerBy(key, this.comparator);\n\t}\n\n\t/**\n\t * Gets the pair associated with the given key or the next higher key.\n\t * @param key - the key to lookup.\n\t * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry\n\t * exists, and undefined otherwise.\n\t */\n\tpublic getPairOrNextHigher(key: K): readonly [K, V] | undefined {\n\t\treturn this.getPairOrNextHigherBy(key, this.comparator);\n\t}\n\n\t/**\n\t * Compares two `AppendOnlySortedMap`s.\n\t */\n\tpublic equals(\n\t\tother: AppendOnlySortedMap<K, V>,\n\t\tcompareValues: (a: V, b: V) => boolean,\n\t): boolean {\n\t\tif (other === this) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (this.elements.length !== other.elements.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = this.elements.length - 2; i >= 0; i -= 2) {\n\t\t\tconst keyThis = this.elements[i] as K;\n\t\t\tconst valueThis = this.elements[i + 1] as V;\n\t\t\tconst keyOther = other.elements[i] as K;\n\t\t\tconst valueOther = other.elements[i + 1] as V;\n\t\t\tif (this.comparator(keyThis, keyOther) !== 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!compareValues(valueThis, valueOther)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test-only expensive assertions to check the internal validity of the data structure.\n\t */\n\tpublic assertValid(): void {\n\t\tlet prev: readonly [K, unknown] | undefined;\n\t\tfor (const kv of this.entries()) {\n\t\t\tif (prev !== undefined) {\n\t\t\t\tassert(this.comparator(kv[0], prev[0]) > 0, 0x752 /* Keys in map must be sorted. */);\n\t\t\t}\n\t\t\tprev = kv;\n\t\t}\n\t}\n\n\t/**\n\t * Queries a range of entries.\n\t * @param from - the key to start the range query at, inclusive.\n\t * @param to - the key to end the range query at, inclusive.\n\t * @returns the range of entries.\n\t */\n\tpublic *getRange(from: K, to: K): IterableIterator<readonly [K, V]> {\n\t\tconst keyIndexFrom = this.getKeyIndexOfOrNextHigher(from, this.comparator);\n\t\tif (keyIndexFrom === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst keyIndexTo = this.getKeyIndexOfOrNextLower(to, this.comparator);\n\t\tif (keyIndexTo === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = keyIndexFrom; i <= keyIndexTo; i += 2) {\n\t\t\tyield [this.elements[i] as K, this.elements[i + 1] as V];\n\t\t}\n\t}\n\n\tprotected getPairOrNextLowerBy<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): readonly [K, V] | undefined {\n\t\tconst keyIndex = this.getKeyIndexOfOrNextLower(search, comparator);\n\t\tif (keyIndex === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn [this.elements[keyIndex] as K, this.elements[keyIndex + 1] as V];\n\t}\n\n\tprivate getKeyIndexOfOrNextLower<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): number | undefined {\n\t\tconst { elements } = this;\n\t\tif (elements.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tlet keyIndex = AppendOnlySortedMap.keyIndexOf(elements, search, comparator);\n\t\tif (keyIndex < 0) {\n\t\t\tkeyIndex ^= AppendOnlySortedMap.failureXor;\n\t\t\tif (keyIndex > 0) {\n\t\t\t\treturn keyIndex - 2;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\treturn keyIndex;\n\t}\n\n\t/**\n\t * Gets the pair associated with the given key or next higher key.\n\t * @param search - the search value\n\t * @param comparator - a comparison function\n\t * @returns the pair if it exists, or undefined otherwise.\n\t */\n\tprotected getPairOrNextHigherBy<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): readonly [K, V] | undefined {\n\t\tconst keyIndex = this.getKeyIndexOfOrNextHigher(search, comparator);\n\t\tif (keyIndex === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn [this.elements[keyIndex] as K, this.elements[keyIndex + 1] as V];\n\t}\n\n\tprivate getKeyIndexOfOrNextHigher<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): number | undefined {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tlet keyIndex = AppendOnlySortedMap.keyIndexOf(elements, search, comparator);\n\t\tif (keyIndex < 0) {\n\t\t\tkeyIndex ^= AppendOnlySortedMap.failureXor;\n\t\t\tif (keyIndex < length) {\n\t\t\t\treturn keyIndex;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\treturn keyIndex;\n\t}\n\n\t/**\n\t * The value xor'd with the result index when a search fails.\n\t */\n\tpublic static readonly failureXor = -1;\n\n\t/**\n\t * Performs a binary search on the sorted array.\n\t * @returns the index of the key for `search`, or (if not present) the index it would have been inserted into xor'd\n\t * with `failureXor`. Note that negating is not an adequate solution as that could result in -0.\n\t */\n\tpublic static keyIndexOf<T, K, V>(\n\t\telements: readonly (K | V)[],\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): number {\n\t\t// Low, high, and mid are addresses of [K,V] pairs and *not* key indices\n\t\tlet low = 0;\n\t\tlet high = elements.length / 2;\n\t\tlet mid = high >> 1;\n\t\twhile (low < high) {\n\t\t\tconst keyIndex = mid * 2;\n\t\t\tconst c = comparator(search, elements[keyIndex] as K, elements[keyIndex + 1] as V);\n\t\t\tif (c > 0) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (c < 0) {\n\t\t\t\thigh = mid;\n\t\t\t} else if (c === 0) {\n\t\t\t\treturn keyIndex;\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Invalid comparator.\");\n\t\t\t}\n\t\t\tmid = (low + high) >> 1;\n\t\t}\n\t\treturn (mid * 2) ^ AppendOnlySortedMap.failureXor;\n\t}\n}\n"]}
1
+ {"version":3,"file":"appendOnlySortedMap.js","sourceRoot":"","sources":["../src/appendOnlySortedMap.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable no-bitwise */\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\n/**\n * A map in which entries are always added in key-sorted order.\n * Supports appending and searching.\n */\nexport class AppendOnlySortedMap<K, V> {\n\tprotected readonly elements: (K | V)[] = [];\n\n\t/**\n\t * @param comparator - a comparator for keys\n\t */\n\tpublic constructor(protected readonly comparator: (a: K, b: K) => number) {}\n\n\t/**\n\t * Gets the size of the map.\n\t * @returns the number of entries in this map\n\t */\n\tpublic get size(): number {\n\t\treturn this.elements.length / 2;\n\t}\n\n\t/**\n\t * Gets the min key in the map.\n\t * @returns the min key in the map.\n\t */\n\tpublic minKey(): K | undefined {\n\t\treturn this.elements[0] as K | undefined;\n\t}\n\n\t/**\n\t * Gets the max key in the map.\n\t * @returns the max key in the map.\n\t */\n\tpublic maxKey(): K | undefined {\n\t\treturn this.elements[this.elements.length - 2] as K | undefined;\n\t}\n\n\t/**\n\t * Gets the min value in the map.\n\t * @returns the min value in the map.\n\t */\n\tpublic minValue(): V | undefined {\n\t\treturn this.elements[1] as V | undefined;\n\t}\n\n\t/**\n\t * Gets the max value in the map.\n\t * @returns the max value in the map.\n\t */\n\tpublic maxValue(): V | undefined {\n\t\treturn this.elements[this.elements.length - 1] as V | undefined;\n\t}\n\n\t/**\n\t * Gets the first key/value pair in the map.\n\t * @returns the first pair if it exists, or undefined otherwise.\n\t */\n\tpublic first(): [K, V] | undefined {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [elements[0] as K, elements[1] as V];\n\t}\n\n\t/**\n\t * Gets the last key/value pair in the map.\n\t * @returns the last pair if it exists, or undefined otherwise.\n\t */\n\tpublic last(): [K, V] | undefined {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst lastKeyIndex = length - 2;\n\t\treturn [elements[lastKeyIndex] as K, elements[lastKeyIndex + 1] as V];\n\t}\n\n\t/**\n\t * Gets the entry at the specified index.\n\t * @param index - the entry index\n\t * @returns the key/value pair if it exists, or undefined otherwise.\n\t */\n\tpublic getAtIndex(index: number): [K, V] | undefined {\n\t\tconst realIndex = index * 2;\n\t\tconst { elements } = this;\n\t\tif (realIndex < 0 || realIndex > elements.length - 1) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [elements[realIndex] as K, elements[realIndex + 1] as V];\n\t}\n\n\t/**\n\t * Gets the entries in the map.\n\t * @returns an iterable of the entries in the map.\n\t */\n\tpublic *entries(): IterableIterator<readonly [K, V]> {\n\t\tconst { elements } = this;\n\t\tfor (let i = 0; i < elements.length; i += 2) {\n\t\t\tyield [elements[i] as K, elements[i + 1] as V];\n\t\t}\n\t}\n\n\t/**\n\t * Gets the keys in the map.\n\t * @returns an iterable of the keys in the map.\n\t */\n\tpublic *keys(): IterableIterator<K> {\n\t\tconst { elements } = this;\n\t\tfor (let i = 0; i < elements.length; i += 2) {\n\t\t\tyield elements[i] as K;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the values in the map.\n\t * @returns an iterable of the values in the map.\n\t */\n\tpublic *values(): IterableIterator<V> {\n\t\tconst { elements } = this;\n\t\tfor (let i = 0; i < elements.length; i += 2) {\n\t\t\tyield elements[i + 1] as V;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the entries in the map, reversed.\n\t * @returns an iterable of the entries in the map, reversed.\n\t */\n\tpublic *entriesReversed(): IterableIterator<readonly [K, V]> {\n\t\tconst { elements } = this;\n\t\tfor (let i = elements.length - 2; i >= 0; i -= 2) {\n\t\t\tyield [elements[i] as K, elements[i + 1] as V];\n\t\t}\n\t}\n\n\t/**\n\t * Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.\n\t * @param key - the key to add\n\t * @param value - the value to add\n\t */\n\tpublic append(key: K, value: V): void {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length !== 0 && this.comparator(key, this.maxKey() as K) <= 0) {\n\t\t\tthrow new Error(\"Inserted key must be > all others in the map.\");\n\t\t}\n\t\telements.push(key, value);\n\t}\n\n\t/**\n\t * Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.\n\t * 'key' must be greater than all other keys in the map.\n\t * @param key - the key to set\n\t * @param value - the value to set\n\t */\n\tpublic replaceLast(key: K, value: V): void {\n\t\tconst { elements, comparator } = this;\n\t\tconst { length } = elements;\n\t\tif (length !== 0) {\n\t\t\telements.pop();\n\t\t\telements.pop();\n\t\t\tif (comparator(key, this.maxKey() as K) <= 0) {\n\t\t\t\tthrow new Error(\"Inserted key must be > all others in the map.\");\n\t\t\t}\n\t\t}\n\t\telements.push(key, value);\n\t}\n\n\t/**\n\t * Gets the value associated with a given key.\n\t * @param key - the key to lookup\n\t * @returns the value if it exists, or undefined otherwise.\n\t */\n\tpublic get(key: K): V | undefined {\n\t\tconst index = AppendOnlySortedMap.keyIndexOf(this.elements, key, this.comparator);\n\t\tif (index < 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.elements[index + 1] as V;\n\t}\n\n\t/**\n\t * Gets the pair associated with the given key or the next smaller key.\n\t * @param key - the key to lookup\n\t * @returns the pair if it exists, or undefined otherwise.\n\t */\n\tpublic getPairOrNextLower(key: K): readonly [K, V] | undefined {\n\t\treturn this.getPairOrNextLowerBy(key, this.comparator);\n\t}\n\n\t/**\n\t * Gets the pair associated with the given key or the next higher key.\n\t * @param key - the key to lookup.\n\t * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry\n\t * exists, and undefined otherwise.\n\t */\n\tpublic getPairOrNextHigher(key: K): readonly [K, V] | undefined {\n\t\treturn this.getPairOrNextHigherBy(key, this.comparator);\n\t}\n\n\t/**\n\t * Compares two `AppendOnlySortedMap`s.\n\t */\n\tpublic equals(\n\t\tother: AppendOnlySortedMap<K, V>,\n\t\tcompareValues: (a: V, b: V) => boolean,\n\t): boolean {\n\t\tif (other === this) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (this.elements.length !== other.elements.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = this.elements.length - 2; i >= 0; i -= 2) {\n\t\t\tconst keyThis = this.elements[i] as K;\n\t\t\tconst valueThis = this.elements[i + 1] as V;\n\t\t\tconst keyOther = other.elements[i] as K;\n\t\t\tconst valueOther = other.elements[i + 1] as V;\n\t\t\tif (this.comparator(keyThis, keyOther) !== 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!compareValues(valueThis, valueOther)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test-only expensive assertions to check the internal validity of the data structure.\n\t */\n\tpublic assertValid(): void {\n\t\tlet prev: readonly [K, unknown] | undefined;\n\t\tfor (const kv of this.entries()) {\n\t\t\tif (prev !== undefined) {\n\t\t\t\tassert(this.comparator(kv[0], prev[0]) > 0, 0x752 /* Keys in map must be sorted. */);\n\t\t\t}\n\t\t\tprev = kv;\n\t\t}\n\t}\n\n\t/**\n\t * Queries a range of entries.\n\t * @param from - the key to start the range query at, inclusive.\n\t * @param to - the key to end the range query at, inclusive.\n\t * @returns the range of entries.\n\t */\n\tpublic *getRange(from: K, to: K): IterableIterator<readonly [K, V]> {\n\t\tconst keyIndexFrom = this.getKeyIndexOfOrNextHigher(from, this.comparator);\n\t\tif (keyIndexFrom === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst keyIndexTo = this.getKeyIndexOfOrNextLower(to, this.comparator);\n\t\tif (keyIndexTo === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = keyIndexFrom; i <= keyIndexTo; i += 2) {\n\t\t\tyield [this.elements[i] as K, this.elements[i + 1] as V];\n\t\t}\n\t}\n\n\tprotected getPairOrNextLowerBy<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): readonly [K, V] | undefined {\n\t\tconst keyIndex = this.getKeyIndexOfOrNextLower(search, comparator);\n\t\tif (keyIndex === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn [this.elements[keyIndex] as K, this.elements[keyIndex + 1] as V];\n\t}\n\n\tprivate getKeyIndexOfOrNextLower<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): number | undefined {\n\t\tconst { elements } = this;\n\t\tif (elements.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tlet keyIndex = AppendOnlySortedMap.keyIndexOf(elements, search, comparator);\n\t\tif (keyIndex < 0) {\n\t\t\tkeyIndex ^= AppendOnlySortedMap.failureXor;\n\t\t\tif (keyIndex > 0) {\n\t\t\t\treturn keyIndex - 2;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\treturn keyIndex;\n\t}\n\n\t/**\n\t * Gets the pair associated with the given key or next higher key.\n\t * @param search - the search value\n\t * @param comparator - a comparison function\n\t * @returns the pair if it exists, or undefined otherwise.\n\t */\n\tprotected getPairOrNextHigherBy<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): readonly [K, V] | undefined {\n\t\tconst keyIndex = this.getKeyIndexOfOrNextHigher(search, comparator);\n\t\tif (keyIndex === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn [this.elements[keyIndex] as K, this.elements[keyIndex + 1] as V];\n\t}\n\n\tprivate getKeyIndexOfOrNextHigher<T>(\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): number | undefined {\n\t\tconst { elements } = this;\n\t\tconst { length } = elements;\n\t\tif (length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tlet keyIndex = AppendOnlySortedMap.keyIndexOf(elements, search, comparator);\n\t\tif (keyIndex < 0) {\n\t\t\tkeyIndex ^= AppendOnlySortedMap.failureXor;\n\t\t\tif (keyIndex < length) {\n\t\t\t\treturn keyIndex;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\treturn keyIndex;\n\t}\n\n\t/**\n\t * The value xor'd with the result index when a search fails.\n\t */\n\tpublic static readonly failureXor = -1;\n\n\t/**\n\t * Performs a binary search on the sorted array.\n\t * @returns the index of the key for `search`, or (if not present) the index it would have been inserted into xor'd\n\t * with `failureXor`. Note that negating is not an adequate solution as that could result in -0.\n\t */\n\tpublic static keyIndexOf<T, K, V>(\n\t\telements: readonly (K | V)[],\n\t\tsearch: T,\n\t\tcomparator: (search: T, key: K, value: V) => number,\n\t): number {\n\t\t// Low, high, and mid are addresses of [K,V] pairs and *not* key indices\n\t\tlet low = 0;\n\t\tlet high = elements.length / 2;\n\t\tlet mid = high >> 1;\n\t\twhile (low < high) {\n\t\t\tconst keyIndex = mid * 2;\n\t\t\tconst c = comparator(search, elements[keyIndex] as K, elements[keyIndex + 1] as V);\n\t\t\tif (c > 0) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (c < 0) {\n\t\t\t\thigh = mid;\n\t\t\t} else if (c === 0) {\n\t\t\t\treturn keyIndex;\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Invalid comparator.\");\n\t\t\t}\n\t\t\tmid = (low + high) >> 1;\n\t\t}\n\t\treturn (mid * 2) ^ AppendOnlySortedMap.failureXor;\n\t}\n}\n"]}
package/lib/finalSpace.js CHANGED
@@ -10,9 +10,7 @@ import { clustersEqual, lastAllocatedFinal, lastFinalizedFinal, } from "./sessio
10
10
  * ID will always be one greater than the last final ID in the previous cluster (or 0 if there is not one).
11
11
  */
12
12
  export class FinalSpace {
13
- constructor() {
14
- this.clusterList = [];
15
- }
13
+ clusterList = [];
16
14
  get clusters() {
17
15
  return this.clusterList;
18
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"finalSpace.js","sourceRoot":"","sources":["../src/finalSpace.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAG7D,OAAO,EAEN,aAAa,EACb,kBAAkB,EAClB,kBAAkB,GAClB,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,MAAM,OAAO,UAAU;IAAvB;QACkB,gBAAW,GAAgB,EAAE,CAAC;IAoDhD,CAAC;IAlDA,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAEM,cAAc;QACpB,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACtD,CAAC;IAEM,UAAU,CAAC,UAAqB;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,CACL,WAAW,KAAK,SAAS;YACxB,UAAU,CAAC,WAAW,KAAK,WAAW,CAAC,WAAW,GAAG,WAAW,CAAC,QAAQ,EAC1E,KAAK,CAAC,oDAAoD,CAC1D,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACI,mBAAmB;QACzB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,OAAO,WAAW,KAAK,SAAS;YAC/B,CAAC,CAAE,CAAuB;YAC1B,CAAC,CAAE,CAAE,kBAAkB,CAAC,WAAW,CAAY,GAAG,CAAC,CAAuB,CAAC;IAC7E,CAAC;IAED;;;OAGG;IACI,mBAAmB;QACzB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,OAAO,WAAW,KAAK,SAAS;YAC/B,CAAC,CAAE,CAAuB;YAC1B,CAAC,CAAE,CAAE,kBAAkB,CAAC,WAAW,CAAY,GAAG,CAAC,CAAuB,CAAC;IAC7E,CAAC;IAEM,MAAM,CAAC,KAAiB;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAc,CAAC;YACjD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAc,CAAC,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;IAC7D,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { FinalCompressedId } from \"./identifiers.js\";\nimport {\n\ttype IdCluster,\n\tclustersEqual,\n\tlastAllocatedFinal,\n\tlastFinalizedFinal,\n} from \"./sessions.js\";\n\n/**\n * All IDs that have been finalized (acked), grouped into clusters sorted by their base final IDs.\n * These clusters span the positive integer space and are not sparse, meaning a cluster's base final\n * ID will always be one greater than the last final ID in the previous cluster (or 0 if there is not one).\n */\nexport class FinalSpace {\n\tprivate readonly clusterList: IdCluster[] = [];\n\n\tpublic get clusters(): readonly IdCluster[] {\n\t\treturn this.clusterList;\n\t}\n\n\tpublic getLastCluster(): IdCluster | undefined {\n\t\treturn this.clusterList[this.clusterList.length - 1];\n\t}\n\n\tpublic addCluster(newCluster: IdCluster): void {\n\t\tconst lastCluster = this.getLastCluster();\n\t\tassert(\n\t\t\tlastCluster === undefined ||\n\t\t\t\tnewCluster.baseFinalId === lastCluster.baseFinalId + lastCluster.capacity,\n\t\t\t0x753 /* Cluster insert to final_space is out of order. */,\n\t\t);\n\t\tthis.clusterList.push(newCluster);\n\t}\n\n\t/**\n\t * Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.\n\t * Note: this does not include allocated but unfinalized space in clusters.\n\t */\n\tpublic getFinalizedIdLimit(): FinalCompressedId {\n\t\tconst lastCluster = this.getLastCluster();\n\t\treturn lastCluster === undefined\n\t\t\t? (0 as FinalCompressedId)\n\t\t\t: (((lastFinalizedFinal(lastCluster) as number) + 1) as FinalCompressedId);\n\t}\n\n\t/**\n\t * Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.\n\t * Note: this does includes all allocated IDs in clusters.\n\t */\n\tpublic getAllocatedIdLimit(): FinalCompressedId {\n\t\tconst lastCluster = this.getLastCluster();\n\t\treturn lastCluster === undefined\n\t\t\t? (0 as FinalCompressedId)\n\t\t\t: (((lastAllocatedFinal(lastCluster) as number) + 1) as FinalCompressedId);\n\t}\n\n\tpublic equals(other: FinalSpace): boolean {\n\t\tfor (let i = 0; i < this.clusterList.length; i++) {\n\t\t\tconst cluster = this.clusterList[i] as IdCluster;\n\t\t\tif (!clustersEqual(cluster, other.clusterList[i] as IdCluster)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn this.clusterList.length === other.clusterList.length;\n\t}\n}\n"]}
1
+ {"version":3,"file":"finalSpace.js","sourceRoot":"","sources":["../src/finalSpace.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAG7D,OAAO,EAEN,aAAa,EACb,kBAAkB,EAClB,kBAAkB,GAClB,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,MAAM,OAAO,UAAU;IACL,WAAW,GAAgB,EAAE,CAAC;IAE/C,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAEM,cAAc;QACpB,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACtD,CAAC;IAEM,UAAU,CAAC,UAAqB;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,CACL,WAAW,KAAK,SAAS;YACxB,UAAU,CAAC,WAAW,KAAK,WAAW,CAAC,WAAW,GAAG,WAAW,CAAC,QAAQ,EAC1E,KAAK,CAAC,oDAAoD,CAC1D,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACI,mBAAmB;QACzB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,OAAO,WAAW,KAAK,SAAS;YAC/B,CAAC,CAAE,CAAuB;YAC1B,CAAC,CAAE,CAAE,kBAAkB,CAAC,WAAW,CAAY,GAAG,CAAC,CAAuB,CAAC;IAC7E,CAAC;IAED;;;OAGG;IACI,mBAAmB;QACzB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,OAAO,WAAW,KAAK,SAAS;YAC/B,CAAC,CAAE,CAAuB;YAC1B,CAAC,CAAE,CAAE,kBAAkB,CAAC,WAAW,CAAY,GAAG,CAAC,CAAuB,CAAC;IAC7E,CAAC;IAEM,MAAM,CAAC,KAAiB;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAc,CAAC;YACjD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAc,CAAC,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;IAC7D,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { FinalCompressedId } from \"./identifiers.js\";\nimport {\n\ttype IdCluster,\n\tclustersEqual,\n\tlastAllocatedFinal,\n\tlastFinalizedFinal,\n} from \"./sessions.js\";\n\n/**\n * All IDs that have been finalized (acked), grouped into clusters sorted by their base final IDs.\n * These clusters span the positive integer space and are not sparse, meaning a cluster's base final\n * ID will always be one greater than the last final ID in the previous cluster (or 0 if there is not one).\n */\nexport class FinalSpace {\n\tprivate readonly clusterList: IdCluster[] = [];\n\n\tpublic get clusters(): readonly IdCluster[] {\n\t\treturn this.clusterList;\n\t}\n\n\tpublic getLastCluster(): IdCluster | undefined {\n\t\treturn this.clusterList[this.clusterList.length - 1];\n\t}\n\n\tpublic addCluster(newCluster: IdCluster): void {\n\t\tconst lastCluster = this.getLastCluster();\n\t\tassert(\n\t\t\tlastCluster === undefined ||\n\t\t\t\tnewCluster.baseFinalId === lastCluster.baseFinalId + lastCluster.capacity,\n\t\t\t0x753 /* Cluster insert to final_space is out of order. */,\n\t\t);\n\t\tthis.clusterList.push(newCluster);\n\t}\n\n\t/**\n\t * Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.\n\t * Note: this does not include allocated but unfinalized space in clusters.\n\t */\n\tpublic getFinalizedIdLimit(): FinalCompressedId {\n\t\tconst lastCluster = this.getLastCluster();\n\t\treturn lastCluster === undefined\n\t\t\t? (0 as FinalCompressedId)\n\t\t\t: (((lastFinalizedFinal(lastCluster) as number) + 1) as FinalCompressedId);\n\t}\n\n\t/**\n\t * Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.\n\t * Note: this does includes all allocated IDs in clusters.\n\t */\n\tpublic getAllocatedIdLimit(): FinalCompressedId {\n\t\tconst lastCluster = this.getLastCluster();\n\t\treturn lastCluster === undefined\n\t\t\t? (0 as FinalCompressedId)\n\t\t\t: (((lastAllocatedFinal(lastCluster) as number) + 1) as FinalCompressedId);\n\t}\n\n\tpublic equals(other: FinalSpace): boolean {\n\t\tfor (let i = 0; i < this.clusterList.length; i++) {\n\t\t\tconst cluster = this.clusterList[i] as IdCluster;\n\t\t\tif (!clustersEqual(cluster, other.clusterList[i] as IdCluster)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn this.clusterList.length === other.clusterList.length;\n\t}\n}\n"]}
@@ -26,37 +26,47 @@ function rangeFinalizationError(expectedStart, actualStart) {
26
26
  * See {@link IIdCompressor} and {@link IIdCompressorCore}
27
27
  */
28
28
  export class IdCompressor {
29
+ logger;
30
+ /**
31
+ * Max allowed initial cluster size.
32
+ */
33
+ static maxClusterSize = 2 ** 20;
34
+ // #region Local state
35
+ localSessionId;
36
+ localSession;
37
+ normalizer = new SessionSpaceNormalizer();
38
+ // The number of IDs generated by the local session
39
+ localGenCount = 0;
40
+ // #endregion
41
+ // #region Final state
42
+ /**
43
+ * The gen count to be annotated on the range returned by the next call to `takeNextCreationRange`.
44
+ * This is advanced to `generatedIdCount` + 1 each time it is called.
45
+ * On the other hand, when `resetUnfinalizedCreationRange` is called,
46
+ * this is moved back to the start of the unfinalized range, to ensure those IDs are included in the next range.
47
+ */
48
+ nextRangeBaseGenCount = 1;
49
+ sessions = new Sessions();
50
+ finalSpace = new FinalSpace();
51
+ // #endregion
52
+ // #region Ephemeral state
53
+ /**
54
+ * Roughly equates to a minimum of 1M sessions before we start allocating 64 bit IDs.
55
+ * Eventually, this can be adjusted dynamically to have cluster reservation policies that
56
+ * optimize the number of eager finals.
57
+ * It is not readonly as it is accessed by tests for clear-box testing.
58
+ */
59
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly
60
+ nextRequestedClusterSize = 512;
61
+ // The number of local IDs generated since the last telemetry was sent.
62
+ telemetryLocalIdCount = 0;
63
+ // The number of eager final IDs generated since the last telemetry was sent.
64
+ telemetryEagerFinalIdCount = 0;
65
+ // The ongoing ghost session, if one exists.
66
+ ongoingGhostSession;
29
67
  // #endregion
30
68
  constructor(localSessionIdOrDeserialized, logger) {
31
69
  this.logger = logger;
32
- this.normalizer = new SessionSpaceNormalizer();
33
- // The number of IDs generated by the local session
34
- this.localGenCount = 0;
35
- // #endregion
36
- // #region Final state
37
- /**
38
- * The gen count to be annotated on the range returned by the next call to `takeNextCreationRange`.
39
- * This is advanced to `generatedIdCount` + 1 each time it is called.
40
- * On the other hand, when `resetUnfinalizedCreationRange` is called,
41
- * this is moved back to the start of the unfinalized range, to ensure those IDs are included in the next range.
42
- */
43
- this.nextRangeBaseGenCount = 1;
44
- this.sessions = new Sessions();
45
- this.finalSpace = new FinalSpace();
46
- // #endregion
47
- // #region Ephemeral state
48
- /**
49
- * Roughly equates to a minimum of 1M sessions before we start allocating 64 bit IDs.
50
- * Eventually, this can be adjusted dynamically to have cluster reservation policies that
51
- * optimize the number of eager finals.
52
- * It is not readonly as it is accessed by tests for clear-box testing.
53
- */
54
- // eslint-disable-next-line @typescript-eslint/prefer-readonly
55
- this.nextRequestedClusterSize = 512;
56
- // The number of local IDs generated since the last telemetry was sent.
57
- this.telemetryLocalIdCount = 0;
58
- // The number of eager final IDs generated since the last telemetry was sent.
59
- this.telemetryEagerFinalIdCount = 0;
60
70
  if (typeof localSessionIdOrDeserialized === "string") {
61
71
  this.localSessionId = localSessionIdOrDeserialized;
62
72
  this.localSession = this.sessions.getOrCreate(localSessionIdOrDeserialized);
@@ -554,10 +564,6 @@ export class IdCompressor {
554
564
  this.finalSpace.equals(other.finalSpace));
555
565
  }
556
566
  }
557
- /**
558
- * Max allowed initial cluster size.
559
- */
560
- IdCompressor.maxClusterSize = 2 ** 20;
561
567
  export function createIdCompressor(sessionIdOrLogger, loggerOrUndefined) {
562
568
  let localSessionId;
563
569
  let logger;