@carbonenginejs/runtime-resource 0.17.0 → 0.18.1

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 (89) hide show
  1. package/dist/format/carbonEffect/CjsCarbonEffectWriter.js +16 -4
  2. package/dist/format/carbonEffect/CjsCarbonEffectWriter.js.map +1 -1
  3. package/dist/format/carbonEffect/backendEngineId.js +1 -3
  4. package/dist/format/carbonEffect/backendEngineId.js.map +1 -1
  5. package/dist/format/carbonEffect/buildCarbonEffectContainer.js +11 -1
  6. package/dist/format/carbonEffect/buildCarbonEffectContainer.js.map +1 -1
  7. package/dist/format/carbonEffect/carbonEffectBackendBlock.js +38 -1
  8. package/dist/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -1
  9. package/dist/format/carbonEffect/carbonEffectRecords.js +45 -1
  10. package/dist/format/carbonEffect/carbonEffectRecords.js.map +1 -1
  11. package/dist/format/carbonEffect/carbonEffectResourceTransform.js +120 -60
  12. package/dist/format/carbonEffect/carbonEffectResourceTransform.js.map +1 -1
  13. package/dist/format/effect/effectPermutationGraph.js +46 -29
  14. package/dist/format/effect/effectPermutationGraph.js.map +1 -1
  15. package/dist/format/index.js +1 -1
  16. package/dist/formats/dds/core/helpers.js +35 -6
  17. package/dist/formats/dds/core/helpers.js.map +1 -1
  18. package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js +53 -1
  19. package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js.map +1 -1
  20. package/dist/formats/hlsl/core/detailMapFamily.js +1 -1
  21. package/dist/formats/hlsl/core/detailMapFamily.js.map +1 -1
  22. package/dist/formats/hlsl/core/localLightFamily.js +1 -1
  23. package/dist/formats/hlsl/core/localLightFamily.js.map +1 -1
  24. package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js +10 -1
  25. package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js.map +1 -1
  26. package/dist/formats/index.js +3 -0
  27. package/dist/formats/index.js.map +1 -1
  28. package/dist/formats/schemabound/CjsSchemaBoundFormat.js +236 -0
  29. package/dist/formats/schemabound/CjsSchemaBoundFormat.js.map +1 -0
  30. package/dist/formats/schemabound/core/schemaBoundErrors.js +9 -0
  31. package/dist/formats/schemabound/core/schemaBoundErrors.js.map +1 -0
  32. package/dist/formats/schemabound/core/schemaBoundValues.js +307 -0
  33. package/dist/formats/schemabound/core/schemaBoundValues.js.map +1 -0
  34. package/dist/formats/schemabound/index.js +2 -0
  35. package/dist/formats/schemabound/index.js.map +1 -0
  36. package/dist/formats/sqlite/CjsSqliteFormat.js +244 -0
  37. package/dist/formats/sqlite/CjsSqliteFormat.js.map +1 -0
  38. package/dist/formats/sqlite/core/sqlitePages.js +159 -0
  39. package/dist/formats/sqlite/core/sqlitePages.js.map +1 -0
  40. package/dist/formats/sqlite/core/sqliteRecords.js +174 -0
  41. package/dist/formats/sqlite/core/sqliteRecords.js.map +1 -0
  42. package/dist/formats/sqlite/core/sqliteSchema.js +100 -0
  43. package/dist/formats/sqlite/core/sqliteSchema.js.map +1 -0
  44. package/dist/formats/sqlite/index.js +2 -0
  45. package/dist/formats/sqlite/index.js.map +1 -0
  46. package/dist/formats/static/CjsStaticFormat.js +220 -0
  47. package/dist/formats/static/CjsStaticFormat.js.map +1 -0
  48. package/dist/formats/static/index.js +2 -0
  49. package/dist/formats/static/index.js.map +1 -0
  50. package/dist/formats/webgl/core/buildGlslEffectContainer.js +3 -1
  51. package/dist/formats/webgl/core/buildGlslEffectContainer.js.map +1 -1
  52. package/dist/formats/webgl/core/effectPackage.js +13 -5
  53. package/dist/formats/webgl/core/effectPackage.js.map +1 -1
  54. package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +10 -2
  55. package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -1
  56. package/dist/formats/webgl/core/glslBackendBlock.js +6 -5
  57. package/dist/formats/webgl/core/glslBackendBlock.js.map +1 -1
  58. package/dist/formats/webgl/core/glslBackendBodySet.js +0 -1
  59. package/dist/formats/webgl/core/glslBackendBodySet.js.map +1 -1
  60. package/dist/formats/webgpu/CjsWebgpuFormat.js +161 -163
  61. package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -1
  62. package/dist/formats/webgpu/core/buildCarbonEffectContainer.js +3 -1
  63. package/dist/formats/webgpu/core/buildCarbonEffectContainer.js.map +1 -1
  64. package/dist/formats/webgpu/core/carbonWebgpu/containerViews.js +179 -131
  65. package/dist/formats/webgpu/core/carbonWebgpu/containerViews.js.map +1 -1
  66. package/dist/formats/webgpu/core/effectBackendBodySet.js +2 -3
  67. package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -1
  68. package/dist/formats/webgpu/core/helpers.js +111 -99
  69. package/dist/formats/webgpu/core/helpers.js.map +1 -1
  70. package/dist/formats/webgpu/core/packageEffect.js +44 -33
  71. package/dist/formats/webgpu/core/packageEffect.js.map +1 -1
  72. package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +9 -1
  73. package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -1
  74. package/dist/resource/shader/reflection/Tr2EffectStageInput.js +14 -0
  75. package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
  76. package/docs/concepts/shader-resource-model.md +34 -1
  77. package/docs/formats/README.md +21 -0
  78. package/docs/formats/carbon-effect-container.md +54 -27
  79. package/docs/formats/schemabound.md +112 -0
  80. package/docs/formats/static.md +119 -0
  81. package/docs/formats/webgl/README.md +5 -3
  82. package/docs/formats/webgpu/README.md +2 -2
  83. package/docs/formats/webgpu/architecture.md +2 -2
  84. package/docs/formats/webgpu/formats/carbon-webgpu.md +24 -6
  85. package/docs/formats/webgpu/guides/effect-packaging.md +1 -2
  86. package/docs/formats/webgpu/reference/api.md +7 -6
  87. package/docs/formats/webgpu/reference/wgsl-compatibility.md +2 -2
  88. package/docs/reference/classes/formats.md +33 -0
  89. package/package.json +5 -2
@@ -0,0 +1,159 @@
1
+ import { SqliteError, ReadVarint } from './sqliteRecords.js';
2
+
3
+ /**
4
+ * SQLite page and b-tree walking, for read-only full table scans.
5
+ *
6
+ * Only the table b-tree is walked. Index pages (`0x02` and `0x0a`) are never
7
+ * visited, because every caller of this format scans a table rather than
8
+ * looking a key up, and an index carries no data a table scan does not.
9
+ */
10
+ const HEADER_SIZE = 100;
11
+ const SIGNATURE = "SQLite format 3\0";
12
+ const PAGE_INTERIOR_TABLE = 0x05;
13
+ const PAGE_LEAF_TABLE = 0x0d;
14
+
15
+ /**
16
+ * Reads and validates the hundred-byte database header.
17
+ *
18
+ * @param {Uint8Array} bytes Whole container.
19
+ * @returns {object} Header fields this reader needs.
20
+ */
21
+ function ReadHeader(bytes) {
22
+ if (bytes.byteLength < HEADER_SIZE) {
23
+ throw SqliteError("A SQLite container is at least 100 bytes.");
24
+ }
25
+ const signature = new TextDecoder("latin1").decode(bytes.subarray(0, 16));
26
+ if (signature !== SIGNATURE) {
27
+ throw SqliteError("Not a SQLite container: the header signature does not match.");
28
+ }
29
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
30
+ const declared = view.getUint16(16, false);
31
+
32
+ // 1 is the documented spelling of 65536, which does not fit the field.
33
+ const pageSize = declared === 1 ? 65536 : declared;
34
+ if (pageSize < 512 || (pageSize & pageSize - 1) !== 0) {
35
+ throw SqliteError(`Invalid SQLite page size ${pageSize}.`);
36
+ }
37
+ const encoding = view.getUint32(56, false) || 1;
38
+ return {
39
+ pageSize,
40
+ reserved: view.getUint8(20),
41
+ encoding,
42
+ pageCount: view.getUint32(28, false),
43
+ usableSize: pageSize - view.getUint8(20)
44
+ };
45
+ }
46
+
47
+ /**
48
+ * Returns the bytes of one page, numbered from 1 as the format numbers them.
49
+ */
50
+ function Page(bytes, header, pageNumber) {
51
+ const start = (pageNumber - 1) * header.pageSize;
52
+ if (start < 0 || start + header.pageSize > bytes.byteLength) {
53
+ throw SqliteError(`Page ${pageNumber} is outside the container.`);
54
+ }
55
+ return bytes.subarray(start, start + header.pageSize);
56
+ }
57
+
58
+ /**
59
+ * Joins a cell payload with its overflow chain.
60
+ *
61
+ * The split point is the fiddly part of the format: a payload larger than the
62
+ * local maximum keeps `K` or `M` bytes on the page and puts the rest on a chain
63
+ * of overflow pages, each beginning with a four-byte next-page pointer. Getting
64
+ * this wrong truncates long values rather than failing, which is why the JSON
65
+ * documents in these containers are the case that exposes it.
66
+ */
67
+ function ReadPayload(bytes, header, page, offset, size) {
68
+ const usable = header.usableSize;
69
+ const maxLocal = usable - 35;
70
+ let local = size;
71
+ if (size > maxLocal) {
72
+ const minLocal = Math.floor((usable - 12) * 32 / 255) - 23;
73
+ const K = minLocal + (size - minLocal) % (usable - 4);
74
+ local = K <= maxLocal ? K : minLocal;
75
+ }
76
+ const payload = new Uint8Array(size);
77
+ payload.set(page.subarray(offset, offset + local), 0);
78
+ if (local === size) {
79
+ // Wholly local, so there is no overflow pointer after it to read - and on
80
+ // the last cell of a page, reading one anyway runs off the end.
81
+ return payload;
82
+ }
83
+ let written = local;
84
+ let next = new DataView(page.buffer, page.byteOffset, page.byteLength).getUint32(offset + local, false);
85
+ while (written < size) {
86
+ if (!next) {
87
+ throw SqliteError("An overflow chain ended before the payload was complete.");
88
+ }
89
+ const overflow = Page(bytes, header, next);
90
+ const view = new DataView(overflow.buffer, overflow.byteOffset, overflow.byteLength);
91
+ const take = Math.min(usable - 4, size - written);
92
+ payload.set(overflow.subarray(4, 4 + take), written);
93
+ written += take;
94
+ next = view.getUint32(0, false);
95
+ }
96
+ return payload;
97
+ }
98
+
99
+ /**
100
+ * Walks one table b-tree and yields every leaf cell.
101
+ *
102
+ * @param {Uint8Array} bytes Whole container.
103
+ * @param {object} header Parsed database header.
104
+ * @param {number} rootPage Page number the table is rooted at.
105
+ * @yields {{ rowid: number, payload: Uint8Array }} Each row.
106
+ */
107
+ function* TableRows(bytes, header, rootPage) {
108
+ const stack = [rootPage];
109
+ const seen = new Set();
110
+ while (stack.length) {
111
+ const pageNumber = stack.pop();
112
+
113
+ // A malformed or hostile container could point a page at itself.
114
+ if (seen.has(pageNumber)) {
115
+ throw SqliteError(`Page ${pageNumber} appears twice in one b-tree.`);
116
+ }
117
+ seen.add(pageNumber);
118
+ const page = Page(bytes, header, pageNumber);
119
+ // Page 1 carries the database header before its b-tree header.
120
+ const base = pageNumber === 1 ? HEADER_SIZE : 0;
121
+ const view = new DataView(page.buffer, page.byteOffset, page.byteLength);
122
+ const type = view.getUint8(base);
123
+ const cellCount = view.getUint16(base + 3, false);
124
+ if (type !== PAGE_LEAF_TABLE && type !== PAGE_INTERIOR_TABLE) {
125
+ throw SqliteError(`Page ${pageNumber} is not a table b-tree page (type ${type}).`);
126
+ }
127
+ const headerSize = type === PAGE_INTERIOR_TABLE ? 12 : 8;
128
+ const pointers = base + headerSize;
129
+ if (type === PAGE_INTERIOR_TABLE) {
130
+ // Children are in ascending key order, with the rightmost hanging off the
131
+ // page header rather than off a cell. They go on the stack backwards so
132
+ // that popping visits them in order: rows come out in rowid order, which
133
+ // is what every other SQLite reader produces and what a caller diffing
134
+ // two exports will assume.
135
+ const children = [];
136
+ for (let index = 0; index < cellCount; index += 1) {
137
+ children.push(view.getUint32(view.getUint16(pointers + index * 2, false), false));
138
+ }
139
+ children.push(view.getUint32(base + 8, false));
140
+ for (let index = children.length - 1; index >= 0; index -= 1) {
141
+ stack.push(children[index]);
142
+ }
143
+ continue;
144
+ }
145
+ for (let index = 0; index < cellCount; index += 1) {
146
+ const cell = view.getUint16(pointers + index * 2, false);
147
+ const size = ReadVarint(page, cell);
148
+ const rowid = ReadVarint(page, cell + size.size);
149
+ const start = cell + size.size + rowid.size;
150
+ yield {
151
+ rowid: rowid.value,
152
+ payload: ReadPayload(bytes, header, page, start, size.value)
153
+ };
154
+ }
155
+ }
156
+ }
157
+
158
+ export { HEADER_SIZE, ReadHeader, SIGNATURE, TableRows };
159
+ //# sourceMappingURL=sqlitePages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlitePages.js","sources":["../../../../../src/formats/sqlite/core/sqlitePages.js"],"sourcesContent":["/**\n * SQLite page and b-tree walking, for read-only full table scans.\n *\n * Only the table b-tree is walked. Index pages (`0x02` and `0x0a`) are never\n * visited, because every caller of this format scans a table rather than\n * looking a key up, and an index carries no data a table scan does not.\n */\nimport { ReadVarint, SqliteError } from \"./sqliteRecords.js\";\n\nconst HEADER_SIZE = 100;\nconst SIGNATURE = \"SQLite format 3\\0\";\nconst PAGE_INTERIOR_TABLE = 0x05;\nconst PAGE_LEAF_TABLE = 0x0d;\n\n/**\n * Reads and validates the hundred-byte database header.\n *\n * @param {Uint8Array} bytes Whole container.\n * @returns {object} Header fields this reader needs.\n */\nexport function ReadHeader(bytes) {\n if (bytes.byteLength < HEADER_SIZE) {\n throw SqliteError(\"A SQLite container is at least 100 bytes.\");\n }\n\n const signature = new TextDecoder(\"latin1\").decode(bytes.subarray(0, 16));\n\n if (signature !== SIGNATURE) {\n throw SqliteError(\"Not a SQLite container: the header signature does not match.\");\n }\n\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const declared = view.getUint16(16, false);\n\n // 1 is the documented spelling of 65536, which does not fit the field.\n const pageSize = declared === 1 ? 65536 : declared;\n\n if (pageSize < 512 || (pageSize & (pageSize - 1)) !== 0) {\n throw SqliteError(`Invalid SQLite page size ${pageSize}.`);\n }\n\n const encoding = view.getUint32(56, false) || 1;\n\n return {\n pageSize,\n reserved: view.getUint8(20),\n encoding,\n pageCount: view.getUint32(28, false),\n usableSize: pageSize - view.getUint8(20)\n };\n}\n\n/**\n * Returns the bytes of one page, numbered from 1 as the format numbers them.\n */\nfunction Page(bytes, header, pageNumber) {\n const start = (pageNumber - 1) * header.pageSize;\n\n if (start < 0 || start + header.pageSize > bytes.byteLength) {\n throw SqliteError(`Page ${pageNumber} is outside the container.`);\n }\n\n return bytes.subarray(start, start + header.pageSize);\n}\n\n/**\n * Joins a cell payload with its overflow chain.\n *\n * The split point is the fiddly part of the format: a payload larger than the\n * local maximum keeps `K` or `M` bytes on the page and puts the rest on a chain\n * of overflow pages, each beginning with a four-byte next-page pointer. Getting\n * this wrong truncates long values rather than failing, which is why the JSON\n * documents in these containers are the case that exposes it.\n */\nfunction ReadPayload(bytes, header, page, offset, size) {\n const usable = header.usableSize;\n const maxLocal = usable - 35;\n let local = size;\n\n if (size > maxLocal) {\n const minLocal = Math.floor(((usable - 12) * 32) / 255) - 23;\n const K = minLocal + ((size - minLocal) % (usable - 4));\n\n local = K <= maxLocal ? K : minLocal;\n }\n\n const payload = new Uint8Array(size);\n\n payload.set(page.subarray(offset, offset + local), 0);\n\n if (local === size) {\n // Wholly local, so there is no overflow pointer after it to read - and on\n // the last cell of a page, reading one anyway runs off the end.\n return payload;\n }\n\n let written = local;\n let next = new DataView(page.buffer, page.byteOffset, page.byteLength)\n .getUint32(offset + local, false);\n\n while (written < size) {\n if (!next) {\n throw SqliteError(\"An overflow chain ended before the payload was complete.\");\n }\n\n const overflow = Page(bytes, header, next);\n const view = new DataView(overflow.buffer, overflow.byteOffset, overflow.byteLength);\n const take = Math.min(usable - 4, size - written);\n\n payload.set(overflow.subarray(4, 4 + take), written);\n written += take;\n next = view.getUint32(0, false);\n }\n\n return payload;\n}\n\n/**\n * Walks one table b-tree and yields every leaf cell.\n *\n * @param {Uint8Array} bytes Whole container.\n * @param {object} header Parsed database header.\n * @param {number} rootPage Page number the table is rooted at.\n * @yields {{ rowid: number, payload: Uint8Array }} Each row.\n */\nexport function* TableRows(bytes, header, rootPage) {\n const stack = [ rootPage ];\n const seen = new Set();\n\n while (stack.length) {\n const pageNumber = stack.pop();\n\n // A malformed or hostile container could point a page at itself.\n if (seen.has(pageNumber)) {\n throw SqliteError(`Page ${pageNumber} appears twice in one b-tree.`);\n }\n\n seen.add(pageNumber);\n\n const page = Page(bytes, header, pageNumber);\n // Page 1 carries the database header before its b-tree header.\n const base = pageNumber === 1 ? HEADER_SIZE : 0;\n const view = new DataView(page.buffer, page.byteOffset, page.byteLength);\n const type = view.getUint8(base);\n const cellCount = view.getUint16(base + 3, false);\n\n if (type !== PAGE_LEAF_TABLE && type !== PAGE_INTERIOR_TABLE) {\n throw SqliteError(`Page ${pageNumber} is not a table b-tree page (type ${type}).`);\n }\n\n const headerSize = type === PAGE_INTERIOR_TABLE ? 12 : 8;\n const pointers = base + headerSize;\n\n if (type === PAGE_INTERIOR_TABLE) {\n // Children are in ascending key order, with the rightmost hanging off the\n // page header rather than off a cell. They go on the stack backwards so\n // that popping visits them in order: rows come out in rowid order, which\n // is what every other SQLite reader produces and what a caller diffing\n // two exports will assume.\n const children = [];\n\n for (let index = 0; index < cellCount; index += 1) {\n children.push(view.getUint32(view.getUint16(pointers + index * 2, false), false));\n }\n\n children.push(view.getUint32(base + 8, false));\n\n for (let index = children.length - 1; index >= 0; index -= 1) {\n stack.push(children[index]);\n }\n\n continue;\n }\n\n for (let index = 0; index < cellCount; index += 1) {\n const cell = view.getUint16(pointers + index * 2, false);\n const size = ReadVarint(page, cell);\n const rowid = ReadVarint(page, cell + size.size);\n const start = cell + size.size + rowid.size;\n\n yield {\n rowid: rowid.value,\n payload: ReadPayload(bytes, header, page, start, size.value)\n };\n }\n }\n}\n\nexport { HEADER_SIZE, SIGNATURE };\n"],"names":["HEADER_SIZE","SIGNATURE","PAGE_INTERIOR_TABLE","PAGE_LEAF_TABLE","ReadHeader","bytes","byteLength","SqliteError","signature","TextDecoder","decode","subarray","view","DataView","buffer","byteOffset","declared","getUint16","pageSize","encoding","getUint32","reserved","getUint8","pageCount","usableSize","Page","header","pageNumber","start","ReadPayload","page","offset","size","usable","maxLocal","local","minLocal","Math","floor","K","payload","Uint8Array","set","written","next","overflow","take","min","TableRows","rootPage","stack","seen","Set","length","pop","has","add","base","type","cellCount","headerSize","pointers","children","index","push","cell","ReadVarint","rowid","value"],"mappings":"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"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * SQLite record and varint decoding.
3
+ *
4
+ * The file format is documented by SQLite itself; this decodes the read-only
5
+ * subset a full table scan needs and nothing else.
6
+ */
7
+
8
+ const TEXT_DECODERS = Object.freeze({
9
+ 1: "utf-8",
10
+ 2: "utf-16le",
11
+ 3: "utf-16be"
12
+ });
13
+
14
+ /**
15
+ * Reads a big-endian base-128 varint, of one to nine bytes.
16
+ *
17
+ * A ninth byte exists only when all eight before it set their continuation bit,
18
+ * and it contributes all eight of its own bits rather than seven. Treating the
19
+ * eighth byte as that terminator instead - which this did until it was
20
+ * checked - returns size 9 for an eight-byte varint, so the caller skips a byte
21
+ * it never read. No container in the corpus holds a varint long enough to
22
+ * expose it, which is why decoding 80,765 rows correctly proved nothing here.
23
+ *
24
+ * @param {Uint8Array} bytes Buffer to read from.
25
+ * @param {number} offset Byte offset.
26
+ * @returns {{ value: number, size: number }} Value and bytes consumed.
27
+ */
28
+ function ReadVarint(bytes, offset) {
29
+ let value = 0n;
30
+
31
+ // The first eight bytes carry seven bits each, high bit continuing.
32
+ for (let index = 0; index < 8; index += 1) {
33
+ const byte = bytes[offset + index];
34
+ if (byte === undefined) {
35
+ throw SqliteError("A varint runs past the end of the container.");
36
+ }
37
+ value = value << 7n | BigInt(byte & 0x7f);
38
+ if ((byte & 0x80) === 0) {
39
+ return {
40
+ value: Narrow(value),
41
+ size: index + 1
42
+ };
43
+ }
44
+ }
45
+
46
+ // Only when all eight continued does a ninth byte exist, and it contributes
47
+ // all eight of its bits rather than seven - the one irregularity in the
48
+ // encoding, and 8x7 + 8 is where the full 64 bits come from.
49
+ const ninth = bytes[offset + 8];
50
+ if (ninth === undefined) {
51
+ throw SqliteError("A nine-byte varint runs past the end of the container.");
52
+ }
53
+ value = value << 8n | BigInt(ninth);
54
+ return {
55
+ value: Narrow(BigInt.asIntN(64, value)),
56
+ size: 9
57
+ };
58
+ }
59
+
60
+ /**
61
+ * Returns a Number when one holds the value exactly, and the BigInt otherwise.
62
+ *
63
+ * A varint reaches 64 bits, so it can carry a rowid past 2^53 that a Number
64
+ * would silently round. Rounding a key is worse than handing back a type the
65
+ * caller has to notice, and it matches how a record's own wide integers are
66
+ * already returned.
67
+ *
68
+ * Sizes and header lengths never come close, so callers doing arithmetic on
69
+ * those keep seeing Numbers.
70
+ *
71
+ * @param {bigint} value Decoded value.
72
+ * @returns {number|bigint} Narrowed value.
73
+ */
74
+ function Narrow(value) {
75
+ const narrowed = Number(value);
76
+ return Number.isSafeInteger(narrowed) ? narrowed : value;
77
+ }
78
+
79
+ /**
80
+ * Returns the byte length a serial type occupies in a record body.
81
+ *
82
+ * @param {number} serial Serial type code.
83
+ * @returns {number} Byte length.
84
+ */
85
+ function SerialSize(serial) {
86
+ if (serial >= 12) {
87
+ return Math.floor((serial - (serial % 2 === 0 ? 12 : 13)) / 2);
88
+ }
89
+
90
+ // 0 and 8/9 are constants stored entirely in the type; 7 is a double.
91
+ return [0, 1, 2, 3, 4, 6, 8, 8, 0, 0][serial] ?? 0;
92
+ }
93
+
94
+ /**
95
+ * Decodes one serial-typed value from a record body.
96
+ *
97
+ * @param {Uint8Array} body Record body bytes.
98
+ * @param {number} offset Offset within the body.
99
+ * @param {number} serial Serial type code.
100
+ * @param {number} encoding Database text encoding (1, 2 or 3).
101
+ * @returns {*} Decoded value.
102
+ */
103
+ function ReadSerial(body, offset, serial, encoding) {
104
+ if (serial === 0) {
105
+ return null;
106
+ }
107
+ if (serial === 8) {
108
+ return 0;
109
+ }
110
+ if (serial === 9) {
111
+ return 1;
112
+ }
113
+ if (serial >= 1 && serial <= 6) {
114
+ const size = SerialSize(serial);
115
+ let value = 0n;
116
+ for (let index = 0; index < size; index += 1) {
117
+ value = value << 8n | BigInt(body[offset + index]);
118
+ }
119
+
120
+ // These are all signed, so a leading high bit means a negative number.
121
+ const signed = BigInt.asIntN(size * 8, value);
122
+ return Number.isSafeInteger(Number(signed)) ? Number(signed) : signed;
123
+ }
124
+ if (serial === 7) {
125
+ return new DataView(body.buffer, body.byteOffset + offset, 8).getFloat64(0, false);
126
+ }
127
+ const size = SerialSize(serial);
128
+ const slice = body.subarray(offset, offset + size);
129
+
130
+ // Even codes from 12 are blobs; odd codes from 13 are text.
131
+ if (serial % 2 === 0) {
132
+ return slice.slice();
133
+ }
134
+ const label = TEXT_DECODERS[encoding];
135
+ if (!label) {
136
+ throw SqliteError(`Unsupported text encoding ${encoding}.`);
137
+ }
138
+ return new TextDecoder(label).decode(slice);
139
+ }
140
+
141
+ /**
142
+ * Decodes a complete record into its column values.
143
+ *
144
+ * @param {Uint8Array} payload Record bytes, overflow already joined.
145
+ * @param {number} encoding Database text encoding.
146
+ * @returns {Array<*>} Column values in order.
147
+ */
148
+ function ReadRecord(payload, encoding) {
149
+ const header = ReadVarint(payload, 0);
150
+ const serials = [];
151
+ let cursor = header.size;
152
+ while (cursor < header.value) {
153
+ const serial = ReadVarint(payload, cursor);
154
+ serials.push(serial.value);
155
+ cursor += serial.size;
156
+ }
157
+ const values = [];
158
+ let body = header.value;
159
+ for (const serial of serials) {
160
+ values.push(ReadSerial(payload, body, serial, encoding));
161
+ body += SerialSize(serial);
162
+ }
163
+ return values;
164
+ }
165
+
166
+ /** Creates a tagged error, so a caller can tell a malformed container apart. */
167
+ function SqliteError(message) {
168
+ const error = new Error(message);
169
+ error.code = "CJS_SQLITE_INVALID";
170
+ return error;
171
+ }
172
+
173
+ export { ReadRecord, ReadSerial, ReadVarint, SerialSize, SqliteError };
174
+ //# sourceMappingURL=sqliteRecords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqliteRecords.js","sources":["../../../../../src/formats/sqlite/core/sqliteRecords.js"],"sourcesContent":["/**\n * SQLite record and varint decoding.\n *\n * The file format is documented by SQLite itself; this decodes the read-only\n * subset a full table scan needs and nothing else.\n */\n\nconst TEXT_DECODERS = Object.freeze({\n 1: \"utf-8\",\n 2: \"utf-16le\",\n 3: \"utf-16be\"\n});\n\n/**\n * Reads a big-endian base-128 varint, of one to nine bytes.\n *\n * A ninth byte exists only when all eight before it set their continuation bit,\n * and it contributes all eight of its own bits rather than seven. Treating the\n * eighth byte as that terminator instead - which this did until it was\n * checked - returns size 9 for an eight-byte varint, so the caller skips a byte\n * it never read. No container in the corpus holds a varint long enough to\n * expose it, which is why decoding 80,765 rows correctly proved nothing here.\n *\n * @param {Uint8Array} bytes Buffer to read from.\n * @param {number} offset Byte offset.\n * @returns {{ value: number, size: number }} Value and bytes consumed.\n */\nexport function ReadVarint(bytes, offset) {\n let value = 0n;\n\n // The first eight bytes carry seven bits each, high bit continuing.\n for (let index = 0; index < 8; index += 1) {\n const byte = bytes[offset + index];\n\n if (byte === undefined) {\n throw SqliteError(\"A varint runs past the end of the container.\");\n }\n\n value = (value << 7n) | BigInt(byte & 0x7f);\n\n if ((byte & 0x80) === 0) {\n return { value: Narrow(value), size: index + 1 };\n }\n }\n\n // Only when all eight continued does a ninth byte exist, and it contributes\n // all eight of its bits rather than seven - the one irregularity in the\n // encoding, and 8x7 + 8 is where the full 64 bits come from.\n const ninth = bytes[offset + 8];\n\n if (ninth === undefined) {\n throw SqliteError(\"A nine-byte varint runs past the end of the container.\");\n }\n\n value = (value << 8n) | BigInt(ninth);\n\n return { value: Narrow(BigInt.asIntN(64, value)), size: 9 };\n}\n\n/**\n * Returns a Number when one holds the value exactly, and the BigInt otherwise.\n *\n * A varint reaches 64 bits, so it can carry a rowid past 2^53 that a Number\n * would silently round. Rounding a key is worse than handing back a type the\n * caller has to notice, and it matches how a record's own wide integers are\n * already returned.\n *\n * Sizes and header lengths never come close, so callers doing arithmetic on\n * those keep seeing Numbers.\n *\n * @param {bigint} value Decoded value.\n * @returns {number|bigint} Narrowed value.\n */\nfunction Narrow(value) {\n const narrowed = Number(value);\n\n return Number.isSafeInteger(narrowed) ? narrowed : value;\n}\n\n/**\n * Returns the byte length a serial type occupies in a record body.\n *\n * @param {number} serial Serial type code.\n * @returns {number} Byte length.\n */\nexport function SerialSize(serial) {\n if (serial >= 12) {\n return Math.floor((serial - (serial % 2 === 0 ? 12 : 13)) / 2);\n }\n\n // 0 and 8/9 are constants stored entirely in the type; 7 is a double.\n return [ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0 ][serial] ?? 0;\n}\n\n/**\n * Decodes one serial-typed value from a record body.\n *\n * @param {Uint8Array} body Record body bytes.\n * @param {number} offset Offset within the body.\n * @param {number} serial Serial type code.\n * @param {number} encoding Database text encoding (1, 2 or 3).\n * @returns {*} Decoded value.\n */\nexport function ReadSerial(body, offset, serial, encoding) {\n if (serial === 0) {\n return null;\n }\n\n if (serial === 8) {\n return 0;\n }\n\n if (serial === 9) {\n return 1;\n }\n\n if (serial >= 1 && serial <= 6) {\n const size = SerialSize(serial);\n let value = 0n;\n\n for (let index = 0; index < size; index += 1) {\n value = (value << 8n) | BigInt(body[offset + index]);\n }\n\n // These are all signed, so a leading high bit means a negative number.\n const signed = BigInt.asIntN(size * 8, value);\n\n return Number.isSafeInteger(Number(signed)) ? Number(signed) : signed;\n }\n\n if (serial === 7) {\n return new DataView(body.buffer, body.byteOffset + offset, 8).getFloat64(0, false);\n }\n\n const size = SerialSize(serial);\n const slice = body.subarray(offset, offset + size);\n\n // Even codes from 12 are blobs; odd codes from 13 are text.\n if (serial % 2 === 0) {\n return slice.slice();\n }\n\n const label = TEXT_DECODERS[encoding];\n\n if (!label) {\n throw SqliteError(`Unsupported text encoding ${encoding}.`);\n }\n\n return new TextDecoder(label).decode(slice);\n}\n\n/**\n * Decodes a complete record into its column values.\n *\n * @param {Uint8Array} payload Record bytes, overflow already joined.\n * @param {number} encoding Database text encoding.\n * @returns {Array<*>} Column values in order.\n */\nexport function ReadRecord(payload, encoding) {\n const header = ReadVarint(payload, 0);\n const serials = [];\n let cursor = header.size;\n\n while (cursor < header.value) {\n const serial = ReadVarint(payload, cursor);\n\n serials.push(serial.value);\n cursor += serial.size;\n }\n\n const values = [];\n let body = header.value;\n\n for (const serial of serials) {\n values.push(ReadSerial(payload, body, serial, encoding));\n body += SerialSize(serial);\n }\n\n return values;\n}\n\n/** Creates a tagged error, so a caller can tell a malformed container apart. */\nexport function SqliteError(message) {\n const error = new Error(message);\n\n error.code = \"CJS_SQLITE_INVALID\";\n\n return error;\n}\n"],"names":["TEXT_DECODERS","Object","freeze","ReadVarint","bytes","offset","value","index","byte","undefined","SqliteError","BigInt","Narrow","size","ninth","asIntN","narrowed","Number","isSafeInteger","SerialSize","serial","Math","floor","ReadSerial","body","encoding","signed","DataView","buffer","byteOffset","getFloat64","slice","subarray","label","TextDecoder","decode","ReadRecord","payload","header","serials","cursor","push","values","message","error","Error","code"],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Column names, taken from the `CREATE TABLE` text SQLite stores verbatim.
3
+ *
4
+ * There is no column catalogue in the file: `sqlite_master` keeps the original
5
+ * statement and nothing else, so the names have to come from parsing it. This
6
+ * reads the column list only — enough to name values — and does not attempt to
7
+ * understand types, constraints or expressions.
8
+ */
9
+
10
+ /** Matches the identifier forms SQLite accepts for a column name. */
11
+ const IDENTIFIER = /^(?:"((?:[^"]|"")*)"|`((?:[^`]|``)*)`|\[([^\]]*)\]|([A-Za-z_][A-Za-z0-9_$]*))/u;
12
+
13
+ /** Clauses that begin a table constraint rather than a column definition. */
14
+ const CONSTRAINTS = new Set(["constraint", "primary", "unique", "check", "foreign"]);
15
+
16
+ /**
17
+ * Splits the column list at top-level commas.
18
+ *
19
+ * Depth tracking matters because a column can carry a parenthesised type or
20
+ * check, and quoted text can contain either a comma or a bracket.
21
+ */
22
+ function SplitColumns(body) {
23
+ const parts = [];
24
+ let depth = 0;
25
+ let quote = null;
26
+ let start = 0;
27
+ for (let index = 0; index < body.length; index += 1) {
28
+ const character = body[index];
29
+ if (quote) {
30
+ if (character === quote) {
31
+ quote = null;
32
+ }
33
+ continue;
34
+ }
35
+ if (character === "\"" || character === "'" || character === "`") {
36
+ quote = character;
37
+ } else if (character === "[") {
38
+ quote = "]";
39
+ } else if (character === "(") {
40
+ depth += 1;
41
+ } else if (character === ")") {
42
+ depth -= 1;
43
+ } else if (character === "," && depth === 0) {
44
+ parts.push(body.slice(start, index));
45
+ start = index + 1;
46
+ }
47
+ }
48
+ parts.push(body.slice(start));
49
+ return parts;
50
+ }
51
+
52
+ /**
53
+ * Returns the column names declared by one `CREATE TABLE` statement.
54
+ *
55
+ * @param {string} sql Statement as stored in `sqlite_master`.
56
+ * @returns {{ names: string[], rowidAlias: number }} Names in declaration
57
+ * order, and the index of an `INTEGER PRIMARY KEY` column if there is one.
58
+ */
59
+ function ReadColumns(sql) {
60
+ const open = sql.indexOf("(");
61
+ const close = sql.lastIndexOf(")");
62
+ if (open < 0 || close < open) {
63
+ return {
64
+ names: [],
65
+ rowidAlias: -1
66
+ };
67
+ }
68
+ const names = [];
69
+ let rowidAlias = -1;
70
+ for (const part of SplitColumns(sql.slice(open + 1, close))) {
71
+ const text = part.trim();
72
+ if (!text) {
73
+ continue;
74
+ }
75
+ const match = IDENTIFIER.exec(text);
76
+ if (!match) {
77
+ continue;
78
+ }
79
+ const name = (match[1] ?? match[2] ?? match[3] ?? match[4]).replace(/""/gu, "\"").replace(/``/gu, "`");
80
+
81
+ // A table-level constraint is not a column, and its first word says so.
82
+ if (!match[1] && !match[2] && !match[3] && CONSTRAINTS.has(name.toLowerCase())) {
83
+ continue;
84
+ }
85
+
86
+ // An INTEGER PRIMARY KEY column IS the rowid: its record value is stored
87
+ // as NULL and the real value only exists in the cell's rowid field.
88
+ if (/^\s*integer\s+primary\s+key\b/iu.test(text.slice(match[0].length))) {
89
+ rowidAlias = names.length;
90
+ }
91
+ names.push(name);
92
+ }
93
+ return {
94
+ names,
95
+ rowidAlias
96
+ };
97
+ }
98
+
99
+ export { ReadColumns };
100
+ //# sourceMappingURL=sqliteSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqliteSchema.js","sources":["../../../../../src/formats/sqlite/core/sqliteSchema.js"],"sourcesContent":["/**\n * Column names, taken from the `CREATE TABLE` text SQLite stores verbatim.\n *\n * There is no column catalogue in the file: `sqlite_master` keeps the original\n * statement and nothing else, so the names have to come from parsing it. This\n * reads the column list only — enough to name values — and does not attempt to\n * understand types, constraints or expressions.\n */\n\n/** Matches the identifier forms SQLite accepts for a column name. */\nconst IDENTIFIER = /^(?:\"((?:[^\"]|\"\")*)\"|`((?:[^`]|``)*)`|\\[([^\\]]*)\\]|([A-Za-z_][A-Za-z0-9_$]*))/u;\n\n/** Clauses that begin a table constraint rather than a column definition. */\nconst CONSTRAINTS = new Set([\n \"constraint\", \"primary\", \"unique\", \"check\", \"foreign\"\n]);\n\n/**\n * Splits the column list at top-level commas.\n *\n * Depth tracking matters because a column can carry a parenthesised type or\n * check, and quoted text can contain either a comma or a bracket.\n */\nfunction SplitColumns(body) {\n const parts = [];\n let depth = 0;\n let quote = null;\n let start = 0;\n\n for (let index = 0; index < body.length; index += 1) {\n const character = body[index];\n\n if (quote) {\n if (character === quote) {\n quote = null;\n }\n\n continue;\n }\n\n if (character === \"\\\"\" || character === \"'\" || character === \"`\") {\n quote = character;\n } else if (character === \"[\") {\n quote = \"]\";\n } else if (character === \"(\") {\n depth += 1;\n } else if (character === \")\") {\n depth -= 1;\n } else if (character === \",\" && depth === 0) {\n parts.push(body.slice(start, index));\n start = index + 1;\n }\n }\n\n parts.push(body.slice(start));\n\n return parts;\n}\n\n/**\n * Returns the column names declared by one `CREATE TABLE` statement.\n *\n * @param {string} sql Statement as stored in `sqlite_master`.\n * @returns {{ names: string[], rowidAlias: number }} Names in declaration\n * order, and the index of an `INTEGER PRIMARY KEY` column if there is one.\n */\nexport function ReadColumns(sql) {\n const open = sql.indexOf(\"(\");\n const close = sql.lastIndexOf(\")\");\n\n if (open < 0 || close < open) {\n return { names: [], rowidAlias: -1 };\n }\n\n const names = [];\n let rowidAlias = -1;\n\n for (const part of SplitColumns(sql.slice(open + 1, close))) {\n const text = part.trim();\n\n if (!text) {\n continue;\n }\n\n const match = IDENTIFIER.exec(text);\n\n if (!match) {\n continue;\n }\n\n const name = (match[1] ?? match[2] ?? match[3] ?? match[4])\n .replace(/\"\"/gu, \"\\\"\").replace(/``/gu, \"`\");\n\n // A table-level constraint is not a column, and its first word says so.\n if (!match[1] && !match[2] && !match[3] && CONSTRAINTS.has(name.toLowerCase())) {\n continue;\n }\n\n // An INTEGER PRIMARY KEY column IS the rowid: its record value is stored\n // as NULL and the real value only exists in the cell's rowid field.\n if (/^\\s*integer\\s+primary\\s+key\\b/iu.test(text.slice(match[0].length))) {\n rowidAlias = names.length;\n }\n\n names.push(name);\n }\n\n return { names, rowidAlias };\n}\n\nexport default ReadColumns;\n"],"names":["IDENTIFIER","CONSTRAINTS","Set","SplitColumns","body","parts","depth","quote","start","index","length","character","push","slice","ReadColumns","sql","open","indexOf","close","lastIndexOf","names","rowidAlias","part","text","trim","match","exec","name","replace","has","toLowerCase","test"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAMA,UAAU,GAAG,gFAAgF;;AAEnG;AACA,MAAMC,WAAW,GAAG,IAAIC,GAAG,CAAC,CAC1B,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CACtD,CAAC;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,YAAYA,CAACC,IAAI,EAAE;EAC1B,MAAMC,KAAK,GAAG,EAAE;EAChB,IAAIC,KAAK,GAAG,CAAC;EACb,IAAIC,KAAK,GAAG,IAAI;EAChB,IAAIC,KAAK,GAAG,CAAC;AAEb,EAAA,KAAK,IAAIC,KAAK,GAAG,CAAC,EAAEA,KAAK,GAAGL,IAAI,CAACM,MAAM,EAAED,KAAK,IAAI,CAAC,EAAE;AACnD,IAAA,MAAME,SAAS,GAAGP,IAAI,CAACK,KAAK,CAAC;AAE7B,IAAA,IAAIF,KAAK,EAAE;MACT,IAAII,SAAS,KAAKJ,KAAK,EAAE;AACvBA,QAAAA,KAAK,GAAG,IAAI;AACd,MAAA;AAEA,MAAA;AACF,IAAA;IAEA,IAAII,SAAS,KAAK,IAAI,IAAIA,SAAS,KAAK,GAAG,IAAIA,SAAS,KAAK,GAAG,EAAE;AAChEJ,MAAAA,KAAK,GAAGI,SAAS;AACnB,IAAA,CAAC,MAAM,IAAIA,SAAS,KAAK,GAAG,EAAE;AAC5BJ,MAAAA,KAAK,GAAG,GAAG;AACb,IAAA,CAAC,MAAM,IAAII,SAAS,KAAK,GAAG,EAAE;AAC5BL,MAAAA,KAAK,IAAI,CAAC;AACZ,IAAA,CAAC,MAAM,IAAIK,SAAS,KAAK,GAAG,EAAE;AAC5BL,MAAAA,KAAK,IAAI,CAAC;IACZ,CAAC,MAAM,IAAIK,SAAS,KAAK,GAAG,IAAIL,KAAK,KAAK,CAAC,EAAE;MAC3CD,KAAK,CAACO,IAAI,CAACR,IAAI,CAACS,KAAK,CAACL,KAAK,EAAEC,KAAK,CAAC,CAAC;MACpCD,KAAK,GAAGC,KAAK,GAAG,CAAC;AACnB,IAAA;AACF,EAAA;EAEAJ,KAAK,CAACO,IAAI,CAACR,IAAI,CAACS,KAAK,CAACL,KAAK,CAAC,CAAC;AAE7B,EAAA,OAAOH,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASS,WAAWA,CAACC,GAAG,EAAE;AAC/B,EAAA,MAAMC,IAAI,GAAGD,GAAG,CAACE,OAAO,CAAC,GAAG,CAAC;AAC7B,EAAA,MAAMC,KAAK,GAAGH,GAAG,CAACI,WAAW,CAAC,GAAG,CAAC;AAElC,EAAA,IAAIH,IAAI,GAAG,CAAC,IAAIE,KAAK,GAAGF,IAAI,EAAE;IAC5B,OAAO;AAAEI,MAAAA,KAAK,EAAE,EAAE;AAAEC,MAAAA,UAAU,EAAE;KAAI;AACtC,EAAA;EAEA,MAAMD,KAAK,GAAG,EAAE;EAChB,IAAIC,UAAU,GAAG,EAAE;AAEnB,EAAA,KAAK,MAAMC,IAAI,IAAInB,YAAY,CAACY,GAAG,CAACF,KAAK,CAACG,IAAI,GAAG,CAAC,EAAEE,KAAK,CAAC,CAAC,EAAE;AAC3D,IAAA,MAAMK,IAAI,GAAGD,IAAI,CAACE,IAAI,EAAE;IAExB,IAAI,CAACD,IAAI,EAAE;AACT,MAAA;AACF,IAAA;AAEA,IAAA,MAAME,KAAK,GAAGzB,UAAU,CAAC0B,IAAI,CAACH,IAAI,CAAC;IAEnC,IAAI,CAACE,KAAK,EAAE;AACV,MAAA;AACF,IAAA;AAEA,IAAA,MAAME,IAAI,GAAG,CAACF,KAAK,CAAC,CAAC,CAAC,IAAIA,KAAK,CAAC,CAAC,CAAC,IAAIA,KAAK,CAAC,CAAC,CAAC,IAAIA,KAAK,CAAC,CAAC,CAAC,EACvDG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAACA,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;;AAE7C;AACA,IAAA,IAAI,CAACH,KAAK,CAAC,CAAC,CAAC,IAAI,CAACA,KAAK,CAAC,CAAC,CAAC,IAAI,CAACA,KAAK,CAAC,CAAC,CAAC,IAAIxB,WAAW,CAAC4B,GAAG,CAACF,IAAI,CAACG,WAAW,EAAE,CAAC,EAAE;AAC9E,MAAA;AACF,IAAA;;AAEA;AACA;AACA,IAAA,IAAI,iCAAiC,CAACC,IAAI,CAACR,IAAI,CAACV,KAAK,CAACY,KAAK,CAAC,CAAC,CAAC,CAACf,MAAM,CAAC,CAAC,EAAE;MACvEW,UAAU,GAAGD,KAAK,CAACV,MAAM;AAC3B,IAAA;AAEAU,IAAAA,KAAK,CAACR,IAAI,CAACe,IAAI,CAAC;AAClB,EAAA;EAEA,OAAO;IAAEP,KAAK;AAAEC,IAAAA;GAAY;AAC9B;;;;"}
@@ -0,0 +1,2 @@
1
+ export { CjsSqliteFormat, CjsSqliteFormat as default } from './CjsSqliteFormat.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}