@futpib/parser 1.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 (228) hide show
  1. package/.editorconfig +12 -0
  2. package/.gitattributes +2 -0
  3. package/.github/workflows/main.yml +29 -0
  4. package/.yarn/releases/yarn-4.5.3.cjs +934 -0
  5. package/.yarnrc.yml +7 -0
  6. package/build/allSettledStream.d.ts +17 -0
  7. package/build/allSettledStream.js +21 -0
  8. package/build/allSettledStream.test.d.ts +1 -0
  9. package/build/allSettledStream.test.js +56 -0
  10. package/build/apk.d.ts +13 -0
  11. package/build/apk.js +1 -0
  12. package/build/apkParser.d.ts +3 -0
  13. package/build/apkParser.js +135 -0
  14. package/build/apkParser.test.d.ts +1 -0
  15. package/build/apkParser.test.js +22 -0
  16. package/build/arbitrarilySlicedAsyncInterable.d.ts +2 -0
  17. package/build/arbitrarilySlicedAsyncInterable.js +46 -0
  18. package/build/arbitrarilySlicedAsyncInterator.d.ts +2 -0
  19. package/build/arbitrarilySlicedAsyncInterator.js +17 -0
  20. package/build/arbitraryDosDate.d.ts +2 -0
  21. package/build/arbitraryDosDate.js +8 -0
  22. package/build/arbitraryDosDateTime.d.ts +2 -0
  23. package/build/arbitraryDosDateTime.js +9 -0
  24. package/build/arbitraryDosPermissions.d.ts +1 -0
  25. package/build/arbitraryDosPermissions.js +1 -0
  26. package/build/arbitraryFileSystemEntry.d.ts +14 -0
  27. package/build/arbitraryFileSystemEntry.js +12 -0
  28. package/build/arbitraryZip.d.ts +6 -0
  29. package/build/arbitraryZip.js +88 -0
  30. package/build/arbitraryZipEntry.d.ts +3 -0
  31. package/build/arbitraryZipEntry.js +26 -0
  32. package/build/arbitraryZipPermissions.d.ts +8 -0
  33. package/build/arbitraryZipPermissions.js +16 -0
  34. package/build/arbitraryZipStream.d.ts +5 -0
  35. package/build/arbitraryZipStream.js +50 -0
  36. package/build/arrayParser.d.ts +2 -0
  37. package/build/arrayParser.js +30 -0
  38. package/build/arrayParser.test.d.ts +1 -0
  39. package/build/arrayParser.test.js +9 -0
  40. package/build/bsonParser.d.ts +3 -0
  41. package/build/bsonParser.js +70 -0
  42. package/build/bsonParser.test.d.ts +1 -0
  43. package/build/bsonParser.test.js +24 -0
  44. package/build/createDisjunctionParser.d.ts +2 -0
  45. package/build/createDisjunctionParser.js +47 -0
  46. package/build/createExactParser.d.ts +2 -0
  47. package/build/createExactParser.js +12 -0
  48. package/build/createSequentialUnionParser.d.ts +2 -0
  49. package/build/createSequentialUnionParser.js +69 -0
  50. package/build/debugLogParser.d.ts +2 -0
  51. package/build/debugLogParser.js +23 -0
  52. package/build/disjunctionParser.d.ts +2 -0
  53. package/build/disjunctionParser.js +35 -0
  54. package/build/elementParser.d.ts +3 -0
  55. package/build/elementParser.js +1 -0
  56. package/build/endOfInputParser.d.ts +4 -0
  57. package/build/endOfInputParser.js +4 -0
  58. package/build/exactElementParser.d.ts +3 -0
  59. package/build/exactElementParser.js +6 -0
  60. package/build/exactSequenceParser.d.ts +2 -0
  61. package/build/exactSequenceParser.js +15 -0
  62. package/build/fixedLengthChunkParser.d.ts +2 -0
  63. package/build/fixedLengthChunkParser.js +12 -0
  64. package/build/fixedLengthParser.d.ts +2 -0
  65. package/build/fixedLengthParser.js +12 -0
  66. package/build/fixedLengthSequenceParser.d.ts +2 -0
  67. package/build/fixedLengthSequenceParser.js +16 -0
  68. package/build/index.d.ts +18 -0
  69. package/build/index.js +17 -0
  70. package/build/index.test.d.ts +1 -0
  71. package/build/index.test.js +2 -0
  72. package/build/inputChunkBuffer.d.ts +15 -0
  73. package/build/inputChunkBuffer.js +40 -0
  74. package/build/inputChunkBuffer.test.d.ts +1 -0
  75. package/build/inputChunkBuffer.test.js +34 -0
  76. package/build/inputCompanion.d.ts +18 -0
  77. package/build/inputCompanion.js +28 -0
  78. package/build/inputReader.d.ts +22 -0
  79. package/build/inputReader.js +105 -0
  80. package/build/inputReader.test.d.ts +1 -0
  81. package/build/inputReader.test.js +174 -0
  82. package/build/invariantDefined.d.ts +1 -0
  83. package/build/invariantDefined.js +5 -0
  84. package/build/invariantIdentity.d.ts +3 -0
  85. package/build/invariantIdentity.js +5 -0
  86. package/build/jsonParser.d.ts +3 -0
  87. package/build/jsonParser.js +133 -0
  88. package/build/jsonParser.test.d.ts +1 -0
  89. package/build/jsonParser.test.js +17 -0
  90. package/build/jsonParser2.d.ts +3 -0
  91. package/build/jsonParser2.js +52 -0
  92. package/build/jsonParser2.test.d.ts +1 -0
  93. package/build/jsonParser2.test.js +22 -0
  94. package/build/listParser.d.ts +2 -0
  95. package/build/listParser.js +34 -0
  96. package/build/negativeLookahead.d.ts +2 -0
  97. package/build/negativeLookahead.js +20 -0
  98. package/build/optionalParser.d.ts +2 -0
  99. package/build/optionalParser.js +23 -0
  100. package/build/parser.d.ts +10 -0
  101. package/build/parser.js +53 -0
  102. package/build/parser.test.d.ts +1 -0
  103. package/build/parser.test.js +126 -0
  104. package/build/parserAccessorParser.d.ts +2 -0
  105. package/build/parserAccessorParser.js +1 -0
  106. package/build/parserCompose.d.ts +3 -0
  107. package/build/parserCompose.js +7 -0
  108. package/build/parserContext.d.ts +48 -0
  109. package/build/parserContext.js +193 -0
  110. package/build/parserContext.test.d.ts +1 -0
  111. package/build/parserContext.test.js +115 -0
  112. package/build/parserCreatorCompose.d.ts +3 -0
  113. package/build/parserCreatorCompose.js +10 -0
  114. package/build/parserError.d.ts +43 -0
  115. package/build/parserError.js +61 -0
  116. package/build/parserImplementationInvariant.d.ts +2 -0
  117. package/build/parserImplementationInvariant.js +5 -0
  118. package/build/parserImplementationInvariantInvariant.d.ts +3 -0
  119. package/build/parserImplementationInvariantInvariant.js +15 -0
  120. package/build/parserInvariant.d.ts +4 -0
  121. package/build/parserInvariant.js +11 -0
  122. package/build/parserParsingInvariant.d.ts +1 -0
  123. package/build/parserParsingInvariant.js +1 -0
  124. package/build/promiseCompose.d.ts +1 -0
  125. package/build/promiseCompose.js +3 -0
  126. package/build/promiseFish.d.ts +1 -0
  127. package/build/promiseFish.js +3 -0
  128. package/build/sequence.d.ts +1 -0
  129. package/build/sequence.js +1 -0
  130. package/build/sequenceBuffer.d.ts +15 -0
  131. package/build/sequenceBuffer.js +40 -0
  132. package/build/sequenceBuffer.test.d.ts +1 -0
  133. package/build/sequenceBuffer.test.js +34 -0
  134. package/build/sequenceParser.d.ts +3 -0
  135. package/build/sequenceParser.js +10 -0
  136. package/build/skipParser.d.ts +2 -0
  137. package/build/skipParser.js +8 -0
  138. package/build/sliceBoundedParser.d.ts +2 -0
  139. package/build/sliceBoundedParser.js +24 -0
  140. package/build/sliceBoundedParser.test.d.ts +1 -0
  141. package/build/sliceBoundedParser.test.js +24 -0
  142. package/build/terminatedArrayParser.d.ts +2 -0
  143. package/build/terminatedArrayParser.js +27 -0
  144. package/build/terminatedSequenceParser.d.ts +2 -0
  145. package/build/terminatedSequenceParser.js +24 -0
  146. package/build/tupleParser.d.ts +11 -0
  147. package/build/tupleParser.js +17 -0
  148. package/build/unionParser.d.ts +2 -0
  149. package/build/unionParser.js +68 -0
  150. package/build/zip.d.ts +31 -0
  151. package/build/zip.js +1 -0
  152. package/build/zipEntry.d.ts +28 -0
  153. package/build/zipEntry.js +1 -0
  154. package/build/zipFile.d.ts +32 -0
  155. package/build/zipFile.js +1 -0
  156. package/build/zipFileEntry.d.ts +6 -0
  157. package/build/zipFileEntry.js +1 -0
  158. package/build/zipParser.d.ts +70 -0
  159. package/build/zipParser.js +255 -0
  160. package/build/zipParser.test.d.ts +1 -0
  161. package/build/zipParser.test.js +22 -0
  162. package/package.json +52 -0
  163. package/readme.md +17 -0
  164. package/renovate.json +6 -0
  165. package/src/allSettledStream.test.ts +59 -0
  166. package/src/allSettledStream.test.ts.md +52 -0
  167. package/src/allSettledStream.test.ts.snap +0 -0
  168. package/src/allSettledStream.ts +44 -0
  169. package/src/apk.ts +16 -0
  170. package/src/apkParser.test.ts +30 -0
  171. package/src/apkParser.test.ts.md +268 -0
  172. package/src/apkParser.test.ts.snap +0 -0
  173. package/src/apkParser.ts +327 -0
  174. package/src/arbitrarilySlicedAsyncInterable.ts +73 -0
  175. package/src/arbitrarilySlicedAsyncInterator.ts +25 -0
  176. package/src/arbitraryDosDateTime.ts +10 -0
  177. package/src/arbitraryFileSystemEntry.ts +36 -0
  178. package/src/arbitraryZip.ts +132 -0
  179. package/src/arbitraryZipPermissions.ts +25 -0
  180. package/src/arbitraryZipStream.ts +60 -0
  181. package/src/arrayParser.test.ts +11 -0
  182. package/src/arrayParser.ts +35 -0
  183. package/src/bsonParser.test.ts +37 -0
  184. package/src/bsonParser.ts +131 -0
  185. package/src/debugLogParser.ts +51 -0
  186. package/src/disjunctionParser.ts +55 -0
  187. package/src/elementParser.ts +4 -0
  188. package/src/endOfInputParser.ts +11 -0
  189. package/src/exactElementParser.ts +20 -0
  190. package/src/exactSequenceParser.ts +27 -0
  191. package/src/fixedLengthSequenceParser.ts +24 -0
  192. package/src/index.test.ts +3 -0
  193. package/src/index.ts +76 -0
  194. package/src/inputCompanion.ts +43 -0
  195. package/src/inputReader.test.ts +238 -0
  196. package/src/inputReader.ts +159 -0
  197. package/src/invariantDefined.ts +6 -0
  198. package/src/invariantIdentity.ts +8 -0
  199. package/src/jsonParser.test.ts +26 -0
  200. package/src/jsonParser.ts +225 -0
  201. package/src/listParser.ts +52 -0
  202. package/src/negativeLookahead.ts +26 -0
  203. package/src/optionalParser.ts +27 -0
  204. package/src/parser.test.ts +176 -0
  205. package/src/parser.test.ts.md +68 -0
  206. package/src/parser.test.ts.snap +0 -0
  207. package/src/parser.ts +103 -0
  208. package/src/parserAccessorParser.ts +3 -0
  209. package/src/parserContext.test.ts +154 -0
  210. package/src/parserContext.ts +316 -0
  211. package/src/parserCreatorCompose.ts +23 -0
  212. package/src/parserError.ts +85 -0
  213. package/src/parserImplementationInvariant.ts +6 -0
  214. package/src/parserInvariant.ts +26 -0
  215. package/src/promiseCompose.ts +7 -0
  216. package/src/sequence.ts +10 -0
  217. package/src/sequenceBuffer.test.ts +50 -0
  218. package/src/sequenceBuffer.ts +58 -0
  219. package/src/skipParser.ts +12 -0
  220. package/src/sliceBoundedParser.test.ts +28 -0
  221. package/src/sliceBoundedParser.ts +30 -0
  222. package/src/terminatedArrayParser.ts +40 -0
  223. package/src/tupleParser.ts +33 -0
  224. package/src/unionParser.ts +104 -0
  225. package/src/zip.ts +48 -0
  226. package/src/zipParser.test.ts +31 -0
  227. package/src/zipParser.ts +501 -0
  228. package/tsconfig.json +109 -0
@@ -0,0 +1,30 @@
1
+ import { getParserName, setParserName } from "./parser.js";
2
+ import { ParserParsingFailedError } from "./parserError.js";
3
+ export const createArrayParser = (elementParser) => {
4
+ const arrayParser = async (parserContext) => {
5
+ const elements = [];
6
+ while (true) {
7
+ const elementParserContext = parserContext.lookahead();
8
+ const initialPosition = elementParserContext.position;
9
+ try {
10
+ const element = await elementParser(elementParserContext);
11
+ if (elementParserContext.position === initialPosition) {
12
+ return elements;
13
+ }
14
+ elements.push(element);
15
+ elementParserContext.unlookahead();
16
+ }
17
+ catch (error) {
18
+ if (error instanceof ParserParsingFailedError) {
19
+ return elements;
20
+ }
21
+ throw error;
22
+ }
23
+ finally {
24
+ elementParserContext.dispose();
25
+ }
26
+ }
27
+ };
28
+ setParserName(arrayParser, getParserName(elementParser, 'anonymousArrayChild') + '*');
29
+ return arrayParser;
30
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import test from 'ava';
2
+ import { createArrayParser } from './arrayParser.js';
3
+ import { runParser } from './parser.js';
4
+ import { stringInputCompanion } from './inputCompanion.js';
5
+ test('does not loop forever with a child parser that does not consume anything', async (t) => {
6
+ const parser = createArrayParser(async () => undefined);
7
+ const result = await runParser(parser, 'foo', stringInputCompanion);
8
+ t.deepEqual(result, []);
9
+ });
@@ -0,0 +1,3 @@
1
+ import { type JsonObject } from 'type-fest';
2
+ import { type Parser } from './parser.js';
3
+ export declare const bsonDocumentParser: Parser<JsonObject, Uint8Array>;
@@ -0,0 +1,70 @@
1
+ import { getParserName, setParserName } from './parser.js';
2
+ import { invariantDefined } from './invariantDefined.js';
3
+ import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
4
+ import { promiseCompose } from './promiseCompose.js';
5
+ import { createTupleParser } from './tupleParser.js';
6
+ import { createSkipParser } from './skipParser.js';
7
+ import { createParserAccessorParser } from './parserAccessorParser.js';
8
+ import { createTerminatedArrayParser } from './terminatedArrayParser.js';
9
+ import { createElementParser } from './elementParser.js';
10
+ import { createExactElementParser } from './exactElementParser.js';
11
+ import { createUnionParser } from './unionParser.js';
12
+ import { parserCreatorCompose } from './parserCreatorCompose.js';
13
+ const createFixedLengthBufferParser = (length) => promiseCompose(createFixedLengthSequenceParser(length), sequence => Buffer.from(sequence));
14
+ const buffer1Parser = createFixedLengthBufferParser(1);
15
+ const buffer4Parser = createFixedLengthBufferParser(4);
16
+ const buffer8Parser = createFixedLengthBufferParser(8);
17
+ const elementParser = createElementParser();
18
+ const nullByteParser = createExactElementParser(0);
19
+ const cstringParser = promiseCompose(createTerminatedArrayParser(parserCreatorCompose(() => elementParser, (byte) => async (parserContext) => parserContext.invariant(byte, 'Expected non-null byte'))(), nullByteParser), ([sequence]) => Buffer.from(sequence).toString('utf8'));
20
+ const doubleParser = promiseCompose(buffer8Parser, buffer => buffer.readDoubleLE(0));
21
+ const int32Parser = promiseCompose(buffer4Parser, buffer => buffer.readInt32LE(0));
22
+ const uint32Parser = promiseCompose(buffer4Parser, buffer => buffer.readUInt32LE(0));
23
+ const createFixedLengthStringParser = (length) => promiseCompose(createFixedLengthBufferParser(length), buffer => buffer.toString('utf8'));
24
+ const createFixedLengthNullTerminatedStringParser = (lengthWihoutNullTerminator) => promiseCompose(createTupleParser([
25
+ createFixedLengthStringParser(lengthWihoutNullTerminator),
26
+ nullByteParser,
27
+ ]), ([string]) => string);
28
+ const bsonStringParser = async (parserContext) => {
29
+ const stringSize = await uint32Parser(parserContext);
30
+ return createFixedLengthNullTerminatedStringParser(stringSize - 1)(parserContext);
31
+ };
32
+ const bsonArrayParser = promiseCompose(createTupleParser([
33
+ createSkipParser(4),
34
+ createParserAccessorParser(() => bsonElementListParser),
35
+ ]), ([_, elements]) => elements.map(([_, value]) => value));
36
+ const bsonBooleanParser = async (parserContext) => {
37
+ const booleanValue = invariantDefined(await parserContext.read(0), 'Unexpected end of input');
38
+ return booleanValue === 1;
39
+ };
40
+ const int8Parser = promiseCompose(buffer1Parser, buffer => buffer.readInt8(0));
41
+ const createExactInt8Parser = (value) => parserCreatorCompose(() => int8Parser, actualValue => async (parserContext) => {
42
+ parserContext.invariant(actualValue === value, 'Expected %s, got %s', value, actualValue);
43
+ return actualValue;
44
+ })();
45
+ const createBsonElementParser = (elementType, valueParser) => setParserName(promiseCompose(createTupleParser([
46
+ createExactInt8Parser(elementType),
47
+ cstringParser,
48
+ valueParser,
49
+ ]), ([_, elementName, elementValue]) => [elementName, elementValue]), `bsonElementParser(${elementType}, ${getParserName(valueParser)})`);
50
+ const bsonDoubleElementParser = createBsonElementParser(1, doubleParser);
51
+ const bsonStringElementParser = createBsonElementParser(2, bsonStringParser);
52
+ const bsonDocumentElementParser = createBsonElementParser(3, createParserAccessorParser(() => bsonDocumentParser));
53
+ const bsonArrayElementParser = createBsonElementParser(4, bsonArrayParser);
54
+ const bsonBooleanElementParser = createBsonElementParser(8, bsonBooleanParser);
55
+ const bsonNullElementParser = createBsonElementParser(10, async () => null);
56
+ const bsonInt32ElementParser = createBsonElementParser(16, int32Parser);
57
+ const bsonElementParser = createUnionParser([
58
+ bsonDoubleElementParser,
59
+ bsonStringElementParser,
60
+ bsonDocumentElementParser,
61
+ bsonArrayElementParser,
62
+ bsonBooleanElementParser,
63
+ bsonNullElementParser,
64
+ bsonInt32ElementParser,
65
+ ]);
66
+ const bsonElementListParser = promiseCompose(createTerminatedArrayParser(bsonElementParser, nullByteParser), ([elements]) => elements);
67
+ export const bsonDocumentParser = promiseCompose(createTupleParser([
68
+ createSkipParser(4),
69
+ bsonElementListParser,
70
+ ]), ([_, elements]) => Object.fromEntries(elements));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { testProp, fc } from '@fast-check/ava';
2
+ import { BSON } from 'bson';
3
+ import { bsonDocumentParser } from './bsonParser.js';
4
+ import { arbitrarilySlicedAsyncIterator } from './arbitrarilySlicedAsyncInterator.js';
5
+ import { runParser } from './parser.js';
6
+ import { uint8ArrayInputCompanion } from './inputCompanion.js';
7
+ testProp('bson', [
8
+ arbitrarilySlicedAsyncIterator(fc
9
+ .json()
10
+ .filter(jsonString => {
11
+ // BSON.serialize does not support non-object top-level values
12
+ const jsonValue = JSON.parse(jsonString);
13
+ return (jsonValue !== null
14
+ && typeof jsonValue === 'object'
15
+ && !Array.isArray(jsonValue));
16
+ })
17
+ .map(jsonString => BSON.serialize(JSON.parse(jsonString)))),
18
+ ], async (t, [bsonUint8Array, bsonUint8ArrayChunkIterator]) => {
19
+ const expected = BSON.deserialize(bsonUint8Array);
20
+ const actual = await runParser(bsonDocumentParser, bsonUint8ArrayChunkIterator, uint8ArrayInputCompanion);
21
+ t.deepEqual(actual, expected);
22
+ }, {
23
+ verbose: true,
24
+ });
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createDisjunctionParser: <Output, Sequence>(childParsers: Parser<any, Sequence, any>[]) => Parser<Output, Sequence, unknown>;
@@ -0,0 +1,47 @@
1
+ import { ParserParsingFailedError } from './parserError.js';
2
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
3
+ import { parserParsingInvariant } from './parserParsingInvariant.js';
4
+ function getParserName(parser) {
5
+ return parser.name || 'anonymousDisjunctionChild';
6
+ }
7
+ export const createDisjunctionParser = (childParsers) => {
8
+ parserImplementationInvariant(childParsers.length > 0, 'Disjunction parser must have at least one child parser.');
9
+ const disjunctionParser = async (parserContext) => {
10
+ const parserParsingFailedErrors = [];
11
+ for (const childParser of childParsers) {
12
+ const childParserContext = parserContext.lookahead(getParserName(childParser));
13
+ const [childParserResult] = await Promise.allSettled([childParser(childParserContext)]);
14
+ if (childParserResult.status === 'fulfilled') {
15
+ const successfulParserOutput = childParserResult.value;
16
+ childParserContext.unlookahead();
17
+ childParserContext.dispose();
18
+ return successfulParserOutput;
19
+ }
20
+ else {
21
+ const error = childParserResult.reason;
22
+ if (error instanceof ParserParsingFailedError) {
23
+ parserParsingFailedErrors.push(error);
24
+ }
25
+ else {
26
+ throw error;
27
+ }
28
+ }
29
+ }
30
+ parserParsingInvariant(false, [
31
+ 'No disjunction child parser succeeded.',
32
+ 'Parsing errors, indented, separated by newlines:',
33
+ '%s',
34
+ 'End of parsing errors.',
35
+ ], parserParsingFailedErrors
36
+ .flatMap(error => error.stack?.split('\n'))
37
+ .map(line => ' ' + line)
38
+ .join('\n'));
39
+ };
40
+ const name = [
41
+ '(',
42
+ ...childParsers.map(getParserName).join('|'),
43
+ ')',
44
+ ].join('');
45
+ Object.defineProperty(disjunctionParser, 'name', { value: name });
46
+ return disjunctionParser;
47
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createExactParser: <InputChunk>(inputChunk: InputChunk) => Parser<InputChunk, InputChunk, unknown>;
@@ -0,0 +1,12 @@
1
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
2
+ export const createExactParser = (inputChunk) => {
3
+ parserImplementationInvariant(length > 0, 'Length must be positive.');
4
+ return async (parserContext) => {
5
+ const elements = [];
6
+ for (let i = 0; i < length; i++) {
7
+ const element = await parserContext.read(0);
8
+ elements.push(element);
9
+ }
10
+ return parserContext.from(elements);
11
+ };
12
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createDisjunctionParser: <Output, Sequence>(childParsers: Parser<any, Sequence, any>[]) => Parser<Output, Sequence, unknown>;
@@ -0,0 +1,69 @@
1
+ import { ParserParsingFailedError } from './parserError.js';
2
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
3
+ import { parserParsingInvariant } from './parserParsingInvariant.js';
4
+ function getParserName(parser) {
5
+ return parser.name || 'anonymousSequentialUnionChild';
6
+ }
7
+ export const createDisjunctionParser = (childParsers) => {
8
+ parserImplementationInvariant(childParsers.length > 0, 'SequentialUnion parser must have at least one child parser.');
9
+ const sequentialUnionParser = async (parserContext) => {
10
+ let runningChildParserContexts = [];
11
+ const childParserResults = (async function* () {
12
+ for (const childParser of childParsers) {
13
+ const childParserContext = parserContext.lookahead(getParserName(childParser));
14
+ runningChildParserContexts.push(childParserContext);
15
+ const [promiseSettledResult] = await Promise.allSettled([childParser(childParserContext)]);
16
+ yield {
17
+ ...promiseSettledResult,
18
+ context: childParserContext,
19
+ };
20
+ }
21
+ })();
22
+ const parserParsingFailedErrors = [];
23
+ const successfulParserOutputs = [];
24
+ const successfulParserContexts = [];
25
+ for await (const childParserResult of childParserResults) {
26
+ runningChildParserContexts = runningChildParserContexts.filter(runningChildParserContext => runningChildParserContext !== childParserResult.context);
27
+ if (childParserResult.status === 'fulfilled') {
28
+ successfulParserOutputs.push(childParserResult.value);
29
+ successfulParserContexts.push(childParserResult.context);
30
+ }
31
+ else {
32
+ const error = childParserResult.reason;
33
+ if (error instanceof ParserParsingFailedError) {
34
+ parserParsingFailedErrors.push(error);
35
+ }
36
+ else {
37
+ throw error;
38
+ }
39
+ }
40
+ }
41
+ parserImplementationInvariant(successfulParserOutputs.length <= 1, [
42
+ 'Multiple sequentialUnion child parsers succeeded.',
43
+ 'Successful parser outputs, indented, separated by newlines:',
44
+ '%s',
45
+ 'End of successful parser outputs.',
46
+ ], successfulParserOutputs.map(output => ' ' + JSON.stringify(output)).join('\n'));
47
+ parserParsingInvariant(successfulParserOutputs.length === 1, [
48
+ 'No sequentialUnion child parser succeeded.',
49
+ 'Parsing errors, indented, separated by newlines:',
50
+ '%s',
51
+ 'End of parsing errors.',
52
+ ], parserParsingFailedErrors
53
+ .flatMap(error => error.stack?.split('\n'))
54
+ .map(line => ' ' + line)
55
+ .join('\n'));
56
+ const [successfulParserContext] = successfulParserContexts;
57
+ successfulParserContext.unlookahead();
58
+ successfulParserContext.dispose();
59
+ const [successfulParserOutput] = successfulParserOutputs;
60
+ return successfulParserOutput;
61
+ };
62
+ const name = [
63
+ '(',
64
+ ...childParsers.map(getParserName).join('|'),
65
+ ')',
66
+ ].join('');
67
+ Object.defineProperty(sequentialUnionParser, 'name', { value: name });
68
+ return sequentialUnionParser;
69
+ };
@@ -0,0 +1,2 @@
1
+ import { Parser } from "./parser.js";
2
+ export declare const createDebugLogParser: <Output, Sequence>(childParser: Parser<Output, Sequence>) => Parser<Output, Sequence>;
@@ -0,0 +1,23 @@
1
+ import { getParserName, setParserName } from "./parser.js";
2
+ export const createDebugLogParser = (childParser) => {
3
+ let idCounter = 0;
4
+ const debugLogParser = async (parserContext) => {
5
+ const id = idCounter++;
6
+ const initialPosition = parserContext.position;
7
+ console.debug('%s %s: started (position: %s)', getParserName(childParser), id, initialPosition);
8
+ try {
9
+ const result = await childParser(parserContext);
10
+ console.debug('%s %s: finished (position: %s, consumed: %s): %o', getParserName(childParser), id, parserContext.position, parserContext.position - initialPosition, result);
11
+ return result;
12
+ }
13
+ catch (error) {
14
+ console.debug('%s %s: failed (position: %s, consumed: %s): %o', getParserName(childParser), id, parserContext.position, parserContext.position - initialPosition, error);
15
+ throw error;
16
+ }
17
+ };
18
+ return setParserName(debugLogParser, [
19
+ 'debugLog(',
20
+ getParserName(childParser),
21
+ ')',
22
+ ].join(''));
23
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createDisjunctionParser: <Output, Sequence>(childParsers: Array<Parser<any, Sequence, any>>) => Parser<Output, Sequence, unknown>;
@@ -0,0 +1,35 @@
1
+ import { getParserName, setParserName } from './parser.js';
2
+ import { ParserParsingFailedError } from './parserError.js';
3
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
4
+ export const createDisjunctionParser = (childParsers) => {
5
+ parserImplementationInvariant(childParsers.length > 0, 'Disjunction parser must have at least one child parser.');
6
+ const disjunctionParser = async (parserContext) => {
7
+ const parserParsingFailedErrors = [];
8
+ for (const childParser of childParsers) {
9
+ const childParserContext = parserContext.lookahead({
10
+ debugName: getParserName(childParser, 'anonymousDisjunctionChild'),
11
+ });
12
+ const [childParserResult] = await Promise.allSettled([childParser(childParserContext)]);
13
+ if (childParserResult.status === 'fulfilled') {
14
+ const successfulParserOutput = childParserResult.value;
15
+ childParserContext.unlookahead();
16
+ childParserContext.dispose();
17
+ return successfulParserOutput;
18
+ }
19
+ const error = childParserResult.reason;
20
+ if (error instanceof ParserParsingFailedError) {
21
+ parserParsingFailedErrors.push(error);
22
+ }
23
+ else {
24
+ throw error;
25
+ }
26
+ }
27
+ parserContext.invariantJoin(false, parserParsingFailedErrors, 'No disjunction child parser succeeded.');
28
+ };
29
+ const name = [
30
+ '(',
31
+ ...childParsers.map(childParser => getParserName(childParser, 'anonymousDiscjunctionChild')).join('|'),
32
+ ')',
33
+ ].join('');
34
+ return setParserName(disjunctionParser, name);
35
+ };
@@ -0,0 +1,3 @@
1
+ import { Parser } from "./parser.js";
2
+ import { DeriveSequenceElement } from "./sequence.js";
3
+ export declare const createElementParser: <Sequence, Element = DeriveSequenceElement<Sequence>>() => Parser<Element, Sequence, Element>;
@@ -0,0 +1 @@
1
+ export const createElementParser = () => parserContext => parserContext.read(0);
@@ -0,0 +1,4 @@
1
+ import { Parser } from "./parser.js";
2
+ import { DeriveSequenceElement } from "./sequence.js";
3
+ export declare const createEndOfInputParser: <Sequence, Element = DeriveSequenceElement<Sequence>>() => Parser<void, Sequence, Element>;
4
+ export declare const endOfInputParser: Parser<void, any, any>;
@@ -0,0 +1,4 @@
1
+ export const createEndOfInputParser = () => async (parserContext) => {
2
+ parserContext.invariant(await parserContext.peek(0) === undefined, 'Expected end of input.');
3
+ };
4
+ export const endOfInputParser = createEndOfInputParser();
@@ -0,0 +1,3 @@
1
+ import { type Parser } from './parser.js';
2
+ import { DeriveSequenceElement } from './sequence.js';
3
+ export declare const createExactElementParser: <Sequence, Element = DeriveSequenceElement<Sequence>>(element: Element) => Parser<Element, Sequence, Element>;
@@ -0,0 +1,6 @@
1
+ export const createExactElementParser = (element) => async (parserContext) => {
2
+ const actualElement = await parserContext.peek(0);
3
+ parserContext.invariant(actualElement === element, 'Expected %s, got %s', element, actualElement);
4
+ parserContext.skip(1);
5
+ return element;
6
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createExactSequenceParser: <Sequence>(sequence: Sequence) => Parser<Sequence, Sequence, unknown>;
@@ -0,0 +1,15 @@
1
+ import { inspect } from 'util';
2
+ import { setParserName } from './parser.js';
3
+ export const createExactSequenceParser = (sequence) => {
4
+ const exactSequenceParser = async (parserContext) => {
5
+ const length = parserContext.length(sequence);
6
+ for (let index = 0; index < length; index++) {
7
+ const element = await parserContext.read(0);
8
+ const expectedElement = parserContext.at(sequence, index);
9
+ parserContext.invariant(element === expectedElement, 'Expected "%s", got "%s", at index %s', expectedElement, element, index);
10
+ }
11
+ return sequence;
12
+ };
13
+ setParserName(exactSequenceParser, inspect(sequence));
14
+ return exactSequenceParser;
15
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createFixedLengthParser: <InputChunk>(length: number) => Parser<InputChunk, InputChunk, unknown>;
@@ -0,0 +1,12 @@
1
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
2
+ export const createFixedLengthParser = (length) => {
3
+ parserImplementationInvariant(length > 0, 'Length must be positive.');
4
+ return async (parserContext) => {
5
+ const elements = [];
6
+ for (let i = 0; i < length; i++) {
7
+ const element = await parserContext.read(0);
8
+ elements.push(element);
9
+ }
10
+ return parserContext.from(elements);
11
+ };
12
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createFixedLengthSequenceParser: <Sequence>(length: number) => Parser<Sequence, Sequence, unknown>;
@@ -0,0 +1,12 @@
1
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
2
+ export const createFixedLengthSequenceParser = (length) => {
3
+ parserImplementationInvariant(length >= 0, 'Length must be non-negative got %s.', length);
4
+ return async (parserContext) => {
5
+ const elements = [];
6
+ for (let i = 0; i < length; i++) {
7
+ const element = await parserContext.read(0);
8
+ elements.push(element);
9
+ }
10
+ return parserContext.from(elements);
11
+ };
12
+ };
@@ -0,0 +1,2 @@
1
+ import { type Parser } from './parser.js';
2
+ export declare const createFixedLengthSequenceParser: <Sequence>(lengthInput: bigint | number) => Parser<Sequence, Sequence, unknown>;
@@ -0,0 +1,16 @@
1
+ import { setParserName } from './parser.js';
2
+ import { parserImplementationInvariant } from './parserImplementationInvariant.js';
3
+ export const createFixedLengthSequenceParser = (lengthInput) => {
4
+ const length = BigInt(lengthInput);
5
+ parserImplementationInvariant(length >= 0n, 'Length must be non-negative got %s.', length);
6
+ const fixedLengthSequenceParser = async (parserContext) => {
7
+ const elements = [];
8
+ for (let i = 0n; i < length; i++) {
9
+ const element = await parserContext.read(0);
10
+ elements.push(element);
11
+ }
12
+ return parserContext.from(elements);
13
+ };
14
+ setParserName(fixedLengthSequenceParser, `.{${length}}`);
15
+ return fixedLengthSequenceParser;
16
+ };
@@ -0,0 +1,18 @@
1
+ export { Parser, runParser, setParserName, getParserName, } from './parser.js';
2
+ export { ParserContext, } from './parserContext.js';
3
+ export { createTupleParser, } from './tupleParser.js';
4
+ export { createExactSequenceParser, } from './exactSequenceParser.js';
5
+ export { createFixedLengthSequenceParser, } from './fixedLengthSequenceParser.js';
6
+ export { createArrayParser, } from './arrayParser.js';
7
+ export { createOptionalParser, } from './optionalParser.js';
8
+ export { createUnionParser, } from './unionParser.js';
9
+ export { createDisjunctionParser, } from './disjunctionParser.js';
10
+ export { createParserAccessorParser, } from './parserAccessorParser.js';
11
+ export { createElementParser, } from './elementParser.js';
12
+ export { createTerminatedArrayParser, } from './terminatedArrayParser.js';
13
+ export { createSliceBoundedParser, } from './sliceBoundedParser.js';
14
+ export { createExactElementParser, } from './exactElementParser.js';
15
+ export { createSkipParser, } from './skipParser.js';
16
+ export { createEndOfInputParser, } from './endOfInputParser.js';
17
+ export { createListParser, } from './listParser.js';
18
+ export { createDebugLogParser, } from './debugLogParser.js';
package/build/index.js ADDED
@@ -0,0 +1,17 @@
1
+ export { runParser, setParserName, getParserName, } from './parser.js';
2
+ export { createTupleParser, } from './tupleParser.js';
3
+ export { createExactSequenceParser, } from './exactSequenceParser.js';
4
+ export { createFixedLengthSequenceParser, } from './fixedLengthSequenceParser.js';
5
+ export { createArrayParser, } from './arrayParser.js';
6
+ export { createOptionalParser, } from './optionalParser.js';
7
+ export { createUnionParser, } from './unionParser.js';
8
+ export { createDisjunctionParser, } from './disjunctionParser.js';
9
+ export { createParserAccessorParser, } from './parserAccessorParser.js';
10
+ export { createElementParser, } from './elementParser.js';
11
+ export { createTerminatedArrayParser, } from './terminatedArrayParser.js';
12
+ export { createSliceBoundedParser, } from './sliceBoundedParser.js';
13
+ export { createExactElementParser, } from './exactElementParser.js';
14
+ export { createSkipParser, } from './skipParser.js';
15
+ export { createEndOfInputParser, } from './endOfInputParser.js';
16
+ export { createListParser, } from './listParser.js';
17
+ export { createDebugLogParser, } from './debugLogParser.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import test from 'ava';
2
+ test.todo('TODO');
@@ -0,0 +1,15 @@
1
+ import { type InputCompanion } from './inputCompanion.js';
2
+ export interface SequenceBuffer<Sequence, InputElement> {
3
+ push(sequence: Sequence): void;
4
+ peek(offset: number): InputElement | undefined;
5
+ skip(offset: number): void;
6
+ }
7
+ export declare class SequenceBufferImplementation<Sequence, InputElement> implements SequenceBuffer<Sequence, InputElement> {
8
+ private readonly _inputCompanion;
9
+ private readonly _sequences;
10
+ private _indexInFirstSequence;
11
+ constructor(_inputCompanion: InputCompanion<Sequence, InputElement>);
12
+ push(sequence: Sequence): void;
13
+ peek(offset: number): InputElement | undefined;
14
+ skip(offset: number): void;
15
+ }
@@ -0,0 +1,40 @@
1
+ import invariant from 'invariant';
2
+ export class SequenceBufferImplementation {
3
+ _inputCompanion;
4
+ _sequences = [];
5
+ _indexInFirstSequence = 0;
6
+ constructor(_inputCompanion) {
7
+ this._inputCompanion = _inputCompanion;
8
+ }
9
+ push(sequence) {
10
+ this._sequences.push(sequence);
11
+ while (this._sequences.length > 0) {
12
+ const firstSequence = this._sequences[0];
13
+ const firstSequenceLength = this._inputCompanion.length(firstSequence);
14
+ if (firstSequenceLength === 0) {
15
+ this._sequences.shift();
16
+ continue;
17
+ }
18
+ if (this._indexInFirstSequence < firstSequenceLength) {
19
+ break;
20
+ }
21
+ this._sequences.shift();
22
+ this._indexInFirstSequence -= firstSequenceLength;
23
+ }
24
+ }
25
+ peek(offset) {
26
+ invariant(offset >= 0, 'Offset must be non-negative.');
27
+ let index = this._indexInFirstSequence + offset;
28
+ for (const sequence of this._sequences) {
29
+ const sequenceLength = this._inputCompanion.length(sequence);
30
+ if (index < sequenceLength) {
31
+ return this._inputCompanion.at(sequence, index);
32
+ }
33
+ index -= sequenceLength;
34
+ }
35
+ return undefined;
36
+ }
37
+ skip(offset) {
38
+ this._indexInFirstSequence += offset;
39
+ }
40
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import test from 'ava';
2
+ import { SequenceBufferImplementation } from './sequenceBuffer.js';
3
+ import { stringInputCompanion } from './inputCompanion.js';
4
+ test('sequenceBuffer', t => {
5
+ const sequenceBuffer = new SequenceBufferImplementation(stringInputCompanion);
6
+ t.is(sequenceBuffer.peek(0), undefined);
7
+ sequenceBuffer.push('');
8
+ t.is(sequenceBuffer.peek(0), undefined);
9
+ sequenceBuffer.push('abc');
10
+ t.is(sequenceBuffer.peek(0), 'a');
11
+ t.is(sequenceBuffer.peek(1), 'b');
12
+ t.is(sequenceBuffer.peek(2), 'c');
13
+ t.is(sequenceBuffer.peek(3), undefined);
14
+ sequenceBuffer.push('def');
15
+ t.is(sequenceBuffer.peek(0), 'a');
16
+ t.is(sequenceBuffer.peek(3), 'd');
17
+ t.is(sequenceBuffer.peek(6), undefined);
18
+ sequenceBuffer.push('');
19
+ t.is(sequenceBuffer.peek(0), 'a');
20
+ t.is(sequenceBuffer.peek(3), 'd');
21
+ t.is(sequenceBuffer.peek(6), undefined);
22
+ sequenceBuffer.skip(1);
23
+ t.is(sequenceBuffer.peek(0), 'b');
24
+ t.is(sequenceBuffer.peek(3), 'e');
25
+ t.is(sequenceBuffer.peek(5), undefined);
26
+ sequenceBuffer.skip(3);
27
+ t.is(sequenceBuffer.peek(0), 'e');
28
+ t.is(sequenceBuffer.peek(2), undefined);
29
+ sequenceBuffer.push('gh');
30
+ t.is(sequenceBuffer.peek(0), 'e');
31
+ t.is(sequenceBuffer.peek(2), 'g');
32
+ t.is(sequenceBuffer.peek(3), 'h');
33
+ t.is(sequenceBuffer.peek(4), undefined);
34
+ });
@@ -0,0 +1,18 @@
1
+ export type InputCompanion<Sequence, Element> = {
2
+ is(value: unknown): value is Sequence;
3
+ from(elements: Element[]): Sequence;
4
+ length(sequence: Sequence): number;
5
+ at(sequence: Sequence, index: number): Element | undefined;
6
+ };
7
+ export declare const stringInputCompanion: {
8
+ is(value: unknown): value is string;
9
+ from(elements: string[]): string;
10
+ length(sequence: string): number;
11
+ at(sequence: string, index: number): string | undefined;
12
+ };
13
+ export declare const uint8ArrayInputCompanion: {
14
+ is(value: unknown): value is Uint8Array;
15
+ from(elements: number[]): Uint8Array;
16
+ length(sequence: Uint8Array): number;
17
+ at(sequence: Uint8Array, index: number): number | undefined;
18
+ };