@thomasfosterau/effect-parse 0.1.0 → 0.3.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 (161) hide show
  1. package/README.md +291 -231
  2. package/dist/Ascii.d.ts +32 -53
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +576 -571
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts +6 -29
  7. package/dist/Binary.d.ts.map +1 -1
  8. package/dist/Binary.js +129 -116
  9. package/dist/Binary.js.map +1 -1
  10. package/dist/Bits.d.ts +4 -2
  11. package/dist/Bits.d.ts.map +1 -1
  12. package/dist/Bits.js +121 -123
  13. package/dist/Bits.js.map +1 -1
  14. package/dist/Compiler.d.ts +39 -0
  15. package/dist/Compiler.d.ts.map +1 -0
  16. package/dist/Compiler.js +48 -0
  17. package/dist/Compiler.js.map +1 -0
  18. package/dist/Encoding.d.ts +29 -46
  19. package/dist/Encoding.d.ts.map +1 -1
  20. package/dist/Encoding.js +76 -75
  21. package/dist/Encoding.js.map +1 -1
  22. package/dist/Expression.d.ts +15 -49
  23. package/dist/Expression.d.ts.map +1 -1
  24. package/dist/Expression.js +151 -132
  25. package/dist/Expression.js.map +1 -1
  26. package/dist/Input.d.ts +251 -177
  27. package/dist/Input.d.ts.map +1 -1
  28. package/dist/Input.js +409 -299
  29. package/dist/Input.js.map +1 -1
  30. package/dist/Nom.d.ts +45 -85
  31. package/dist/Nom.d.ts.map +1 -1
  32. package/dist/Nom.js +423 -453
  33. package/dist/Nom.js.map +1 -1
  34. package/dist/ParseError.d.ts +54 -49
  35. package/dist/ParseError.d.ts.map +1 -1
  36. package/dist/ParseError.js +232 -275
  37. package/dist/ParseError.js.map +1 -1
  38. package/dist/Parser.d.ts +345 -313
  39. package/dist/Parser.d.ts.map +1 -1
  40. package/dist/Parser.js +2034 -1802
  41. package/dist/Parser.js.map +1 -1
  42. package/dist/ParserSchema.d.ts +206 -7
  43. package/dist/ParserSchema.d.ts.map +1 -1
  44. package/dist/ParserSchema.js +678 -49
  45. package/dist/ParserSchema.js.map +1 -1
  46. package/dist/ParserStream.d.ts +26 -20
  47. package/dist/ParserStream.d.ts.map +1 -1
  48. package/dist/ParserStream.js +267 -255
  49. package/dist/ParserStream.js.map +1 -1
  50. package/dist/Syntax.d.ts +401 -0
  51. package/dist/Syntax.d.ts.map +1 -0
  52. package/dist/Syntax.js +717 -0
  53. package/dist/Syntax.js.map +1 -0
  54. package/dist/Text.d.ts +98 -134
  55. package/dist/Text.d.ts.map +1 -1
  56. package/dist/Text.js +534 -496
  57. package/dist/Text.js.map +1 -1
  58. package/dist/Token.d.ts +60 -42
  59. package/dist/Token.d.ts.map +1 -1
  60. package/dist/Token.js +331 -265
  61. package/dist/Token.js.map +1 -1
  62. package/dist/index.d.ts +16 -17
  63. package/dist/index.js +16 -17
  64. package/dist/internal/compiler/closure.d.ts +14 -16
  65. package/dist/internal/compiler/closure.d.ts.map +1 -1
  66. package/dist/internal/compiler/closure.js +1458 -1637
  67. package/dist/internal/compiler/closure.js.map +1 -1
  68. package/dist/internal/compiler/entries.d.ts +11 -11
  69. package/dist/internal/compiler/entries.d.ts.map +1 -1
  70. package/dist/internal/compiler/entries.js +36 -26
  71. package/dist/internal/compiler/entries.js.map +1 -1
  72. package/dist/internal/compiler/first.d.ts +19 -19
  73. package/dist/internal/compiler/first.d.ts.map +1 -1
  74. package/dist/internal/compiler/first.js +251 -227
  75. package/dist/internal/compiler/first.js.map +1 -1
  76. package/dist/internal/compiler/jit.d.ts +6 -17
  77. package/dist/internal/compiler/jit.d.ts.map +1 -1
  78. package/dist/internal/compiler/jit.js +860 -988
  79. package/dist/internal/compiler/jit.js.map +1 -1
  80. package/dist/internal/compiler/registry.d.ts +20 -21
  81. package/dist/internal/compiler/registry.d.ts.map +1 -1
  82. package/dist/internal/compiler/registry.js +21 -41
  83. package/dist/internal/compiler/registry.js.map +1 -1
  84. package/dist/internal/compiler/sets.d.ts +9 -13
  85. package/dist/internal/compiler/sets.d.ts.map +1 -1
  86. package/dist/internal/compiler/sets.js +76 -73
  87. package/dist/internal/compiler/sets.js.map +1 -1
  88. package/dist/internal/entries.d.ts +3 -3
  89. package/dist/internal/entries.d.ts.map +1 -1
  90. package/dist/internal/entries.js +38 -30
  91. package/dist/internal/entries.js.map +1 -1
  92. package/dist/internal/node.d.ts +177 -173
  93. package/dist/internal/node.d.ts.map +1 -1
  94. package/dist/internal/node.js +77 -66
  95. package/dist/internal/node.js.map +1 -1
  96. package/dist/internal/numbers.d.ts +7 -8
  97. package/dist/internal/numbers.d.ts.map +1 -1
  98. package/dist/internal/numbers.js +246 -276
  99. package/dist/internal/numbers.js.map +1 -1
  100. package/dist/internal/resume.d.ts +6 -24
  101. package/dist/internal/resume.d.ts.map +1 -1
  102. package/dist/internal/resume.js +30 -29
  103. package/dist/internal/resume.js.map +1 -1
  104. package/dist/internal/run.d.ts +15 -0
  105. package/dist/internal/run.d.ts.map +1 -0
  106. package/dist/internal/run.js +36 -0
  107. package/dist/internal/run.js.map +1 -0
  108. package/dist/internal/stack.d.ts +16 -0
  109. package/dist/internal/stack.d.ts.map +1 -0
  110. package/dist/internal/stack.js +36 -0
  111. package/dist/internal/stack.js.map +1 -0
  112. package/dist/internal/syntax.d.ts +147 -0
  113. package/dist/internal/syntax.d.ts.map +1 -0
  114. package/dist/internal/syntax.js +309 -0
  115. package/dist/internal/syntax.js.map +1 -0
  116. package/dist/internal/text.d.ts +10 -2
  117. package/dist/internal/text.d.ts.map +1 -1
  118. package/dist/internal/text.js +295 -345
  119. package/dist/internal/text.js.map +1 -1
  120. package/dist/internal/ties.d.ts +30 -0
  121. package/dist/internal/ties.d.ts.map +1 -0
  122. package/dist/internal/ties.js +67 -0
  123. package/dist/internal/ties.js.map +1 -0
  124. package/dist/internal/tokens.d.ts +25 -30
  125. package/dist/internal/tokens.d.ts.map +1 -1
  126. package/dist/internal/tokens.js +369 -363
  127. package/dist/internal/tokens.js.map +1 -1
  128. package/package.json +42 -28
  129. package/src/Ascii.ts +278 -187
  130. package/src/Binary.ts +150 -44
  131. package/src/Bits.ts +6 -3
  132. package/src/Compiler.ts +98 -0
  133. package/src/Expression.ts +24 -16
  134. package/src/Input.ts +210 -35
  135. package/src/Nom.ts +4 -3
  136. package/src/ParseError.ts +49 -52
  137. package/src/Parser.ts +1199 -799
  138. package/src/ParserSchema.ts +982 -23
  139. package/src/ParserStream.ts +104 -80
  140. package/src/Syntax.ts +900 -0
  141. package/src/Text.ts +272 -187
  142. package/src/Token.ts +180 -87
  143. package/src/index.ts +2 -0
  144. package/src/internal/compiler/closure.ts +121 -88
  145. package/src/internal/compiler/entries.ts +21 -8
  146. package/src/internal/compiler/first.ts +17 -15
  147. package/src/internal/compiler/jit.ts +360 -157
  148. package/src/internal/compiler/registry.ts +12 -33
  149. package/src/internal/compiler/sets.ts +17 -11
  150. package/src/internal/entries.ts +4 -2
  151. package/src/internal/node.ts +51 -37
  152. package/src/internal/numbers.ts +22 -20
  153. package/src/internal/resume.ts +8 -4
  154. package/src/internal/run.ts +41 -0
  155. package/src/internal/stack.ts +41 -0
  156. package/src/internal/syntax.ts +426 -0
  157. package/src/internal/text.ts +32 -25
  158. package/src/internal/ties.ts +83 -0
  159. package/src/internal/tokens.ts +96 -51
  160. package/dist/index.d.ts.map +0 -1
  161. package/dist/index.js.map +0 -1
@@ -1,270 +1,282 @@
1
+ import * as Predicate from "effect/Predicate";
2
+ import { Fail, Failure, State, fromSource } from "./Input.js";
3
+ import * as Registry from "./internal/compiler/registry.js";
1
4
  import * as Data from "effect/Data";
2
5
  import * as Effect from "effect/Effect";
3
6
  import { dual } from "effect/Function";
4
- import * as Stream from "effect/Stream";
5
- import { Fail, Failure, fromSource, State } from "./Input.js";
6
7
  import * as ParseError from "./ParseError.js";
7
- import * as Compiler from "./internal/compiler/registry.js";
8
+ import * as Run from "./internal/run.js";
9
+ import * as Stack from "./internal/stack.js";
10
+ import * as Stream from "effect/Stream";
11
+ //#region src/ParserStream.ts
12
+ /**
13
+ * Running parsers over Effect `Stream`s of input chunks.
14
+ *
15
+ * This is where nom's and winnow's *partial* (streaming) parsing meets
16
+ * Effect: chunks are buffered and the parser runs in partial mode, so a
17
+ * value split across chunk boundaries is reported as `Incomplete` and
18
+ * retried once more data arrives. When the stream ends, the leftover input
19
+ * is parsed in complete mode.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { Effect, Stream } from "effect"
24
+ * import { Ascii, Parser, ParserStream, Token } from "@thomasfosterau/effect-parse"
25
+ *
26
+ * const line = Parser.terminated(Ascii.decInt, Token.literal("\n"))
27
+ *
28
+ * const program = Stream.make("1\n2", "3\n", "4\n").pipe(
29
+ * ParserStream.parseMany(line),
30
+ * Stream.runCollect
31
+ * )
32
+ * // Effect.runSync(program) => [1, 23, 4]
33
+ * ```
34
+ *
35
+ * @since 0.1.0
36
+ */
8
37
  const concat = (a, b) => {
9
- if (typeof a === "string")
10
- return (a + b);
11
- if (a instanceof Uint8Array) {
12
- if (a.length === 0)
13
- return b;
14
- const out = new Uint8Array(a.length + b.length);
15
- out.set(a);
16
- out.set(b, a.length);
17
- return out;
18
- }
19
- return [...a, ...b];
38
+ if (Predicate.isString(a)) return a + b;
39
+ if (a instanceof Uint8Array) {
40
+ if (a.length === 0) return b;
41
+ const out = new Uint8Array(a.length + b.length);
42
+ out.set(a);
43
+ out.set(b, a.length);
44
+ return out;
45
+ }
46
+ return [...a, ...b];
20
47
  };
21
- const sliceFrom = (input, offset) => (typeof input === "string" ? input.slice(offset) : input.slice(offset));
22
- const noProgress = (input, offset) => ParseError.fromFailure(input, new Failure(offset, "Assert", [], [], false, undefined, "`parseMany` parsers must always consume", 0), "Cut");
48
+ const sliceFrom = (input, offset) => Predicate.isString(input) ? input.slice(offset) : input.slice(offset);
49
+ const noProgress = (input, offset) => ParseError.fromFailure(input, new Failure(offset, "Assert", [], [], false, void 0, "`parseMany` parsers must always consume", 0), "Cut");
23
50
  /**
24
- * Transforms a stream of input chunks into a stream of parsed values by
25
- * applying `parser` repeatedly. Each application must consume input.
26
- *
27
- * Services required by the parser are taken from the stream's context.
28
- * Error offsets are relative to the internal buffer of unconsumed input,
29
- * which is also the `input` of the reported `ParseError`.
30
- *
31
- * @since 0.1.0
32
- * @category combinators
33
- */
34
- export const parseMany = dual((args) => Stream.isStream(args[0]), (self, parser, options) => Stream.suspend(() => {
35
- const step = parser.step;
36
- let buffer = options?.empty === undefined ? undefined : fromSource(options.empty);
37
- const drain = (context, partial) => {
38
- const out = [];
39
- if (buffer === undefined)
40
- return Effect.succeed(out);
41
- const input = buffer;
42
- let offset = 0;
43
- while (offset < input.length) {
44
- const state = new State(input, { partial, context, offset });
45
- const a = step(state);
46
- if (a === Fail) {
47
- if (partial && state.mode === "Incomplete")
48
- break;
49
- return Effect.fail(ParseError.fromFailure(input, state.reportedFailure(), state.mode, state.encoding));
50
- }
51
- if (state.pos === offset)
52
- return Effect.fail(noProgress(input, offset));
53
- out.push(a);
54
- offset = state.pos;
55
- }
56
- buffer = sliceFrom(input, offset);
57
- return Effect.succeed(out);
58
- };
59
- const feed = (source) => Effect.flatMap(Effect.context(), (context) => Effect.suspend(() => {
60
- const chunk = fromSource(source);
61
- buffer = buffer === undefined ? chunk : concat(buffer, chunk);
62
- return drain(context, true);
63
- }));
64
- const finish = Effect.flatMap(Effect.context(), (context) => Effect.suspend(() => drain(context, false)));
65
- return self.pipe(Stream.mapEffect(feed), Stream.flattenIterable, Stream.concat(Stream.unwrap(Effect.map(finish, Stream.fromIterable))));
51
+ * Transforms a stream of input chunks into a stream of parsed values by
52
+ * applying `parser` repeatedly. Each application must consume input.
53
+ *
54
+ * Services required by the parser are taken from the stream's context.
55
+ * Error offsets are relative to the internal buffer of unconsumed input,
56
+ * which is also the `input` of the reported `ParseError`.
57
+ *
58
+ * A parser compiled with the `Compiler` module runs compiled, with the
59
+ * build that handles partial input (see `Parser.run`); a value that fails
60
+ * or needs more input is parsed again interpreted, so errors and
61
+ * `Incomplete` are the interpreter's.
62
+ *
63
+ * @since 0.1.0
64
+ * @category combinators
65
+ */
66
+ const parseMany = /*#__PURE__*/ dual((args) => Stream.isStream(args[0]), (self, parser, options) => Stream.suspend(() => {
67
+ const step = parser.step;
68
+ let buffer = options?.empty === void 0 ? void 0 : fromSource(options.empty);
69
+ const drain = (context, partial) => {
70
+ const out = [];
71
+ if (buffer === void 0) return Effect.succeed(out);
72
+ const input = buffer;
73
+ const state = new State(input);
74
+ let offset = 0;
75
+ while (offset < input.length) {
76
+ state.reset(offset, {
77
+ partial,
78
+ context
79
+ });
80
+ const a = Run.runOn(parser, step, state);
81
+ if (a === Fail) {
82
+ if (partial && state.mode === "Incomplete") break;
83
+ return Effect.fail(ParseError.fromFailure(input, state.reportedFailure(), state.mode, state.encoding));
84
+ }
85
+ if (state.pos === offset) return Effect.fail(noProgress(input, offset));
86
+ out.push(a);
87
+ offset = state.pos;
88
+ }
89
+ buffer = sliceFrom(input, offset);
90
+ return Effect.succeed(out);
91
+ };
92
+ const feed = (source) => Effect.flatMap(Effect.context(), (context) => Effect.suspend(() => {
93
+ const chunk = fromSource(source);
94
+ buffer = buffer === void 0 ? chunk : concat(buffer, chunk);
95
+ return drain(context, true);
96
+ }));
97
+ const finish = Effect.flatMap(Effect.context(), (context) => Effect.suspend(() => drain(context, false)));
98
+ return self.pipe(Stream.mapEffect(feed), Stream.flattenIterable, Stream.concat(Stream.unwrap(Effect.map(finish, Stream.fromIterable))));
66
99
  }));
67
100
  /**
68
- * Parses a stream of chunks incrementally, as one input. Chunks are parsed
69
- * as they arrive, in partial mode; when the parser runs out of input, its
70
- * repetitions keep checkpoints (see `internal/resume.ts`), so the next
71
- * attempt carries on from where the last one stopped instead of starting
72
- * over.
73
- */
74
- class Incremental {
75
- parser;
76
- context;
77
- kind;
78
- text = "";
79
- bytes = new Uint8Array(0);
80
- items = [];
81
- length = 0;
82
- resume = new Map();
83
- /** The input length at the last attempt, and where that attempt ran out of input. */
84
- attempted = 0;
85
- restart = 0;
86
- /** Set once an attempt settles: a success (with its end offset) or a definite failure. */
87
- settled;
88
- constructor(parser, context, empty) {
89
- this.parser = parser;
90
- this.context = context;
91
- if (empty !== undefined)
92
- this.append(empty);
93
- }
94
- append(chunk) {
95
- if (typeof chunk === "string") {
96
- this.kind ??= 0;
97
- this.text += chunk;
98
- this.length += chunk.length;
99
- }
100
- else if (chunk instanceof Uint8Array) {
101
- this.kind ??= 1;
102
- const needed = this.length + chunk.length;
103
- if (needed > this.bytes.length) {
104
- // Grow geometrically, so appending costs amortized constant time per byte
105
- const grown = new Uint8Array(Math.max(needed, this.bytes.length * 2, 4096));
106
- grown.set(this.bytes.subarray(0, this.length));
107
- this.bytes = grown;
108
- }
109
- this.bytes.set(chunk, this.length);
110
- this.length = needed;
111
- }
112
- else {
113
- this.kind ??= 2;
114
- for (let i = 0; i < chunk.length; i++)
115
- this.items.push(chunk[i]);
116
- this.length = this.items.length;
117
- }
118
- }
119
- input() {
120
- switch (this.kind) {
121
- case 1:
122
- return this.bytes.subarray(0, this.length);
123
- case 2:
124
- // Items are only appended between attempts, after each state has read its `end`
125
- return this.items;
126
- default:
127
- return this.text;
128
- }
129
- }
130
- push(chunk) {
131
- if (chunk.length === 0)
132
- return;
133
- this.append(chunk);
134
- if (this.settled !== undefined)
135
- return;
136
- // An attempt re-reads what the last one could not finish, from `restart`;
137
- // waiting until at least half as much new input has arrived keeps the
138
- // total work linear in the input. Strings are also copied when they are
139
- // flattened, so they wait for a fraction of the whole input too.
140
- const added = this.length - this.attempted;
141
- if (added < (this.attempted - this.restart) / 2)
142
- return;
143
- if (this.kind === 0 && added < this.attempted / 8)
144
- return;
145
- this.attempt();
146
- }
147
- /** The step attempts run: the parser's resumable compiled code if it was compiled, else the interpreter. */
148
- step(state) {
149
- return (Compiler.stepFor(this.parser, state, true) ?? this.parser.step)(state);
150
- }
151
- attempt() {
152
- const state = new State(this.input(), { partial: true, context: this.context });
153
- state.resume = this.resume;
154
- const a = this.step(state);
155
- this.attempted = this.length;
156
- if (a !== Fail) {
157
- this.settled = { value: a, pos: state.pos };
158
- }
159
- else if (state.mode === "Incomplete") {
160
- this.restart = state.failure.offset;
161
- }
162
- else {
163
- this.settled = "failed";
164
- }
165
- }
166
- finish() {
167
- const settled = this.settled;
168
- if (settled !== undefined && settled !== "failed") {
169
- if (settled.pos === this.length)
170
- return Effect.succeed(settled.value);
171
- }
172
- else if (settled === undefined) {
173
- // The last attempt, in complete mode, resumes from the checkpoints too
174
- const state = new State(this.input(), { context: this.context });
175
- state.resume = this.resume;
176
- const a = this.step(state);
177
- if (a !== Fail && state.pos === state.end)
178
- return Effect.succeed(a);
179
- }
180
- // The error comes from an ordinary parse of the whole input, so it is the
181
- // same as if the input had been parsed in one go
182
- const all = this.input();
183
- const state = new State(all, { context: this.context });
184
- const a = this.parser.step(state);
185
- if (a !== Fail && state.pos === state.end)
186
- return Effect.succeed(a);
187
- if (a !== Fail)
188
- state.backtrack("Eof", ["end of input"]);
189
- return Effect.fail(ParseError.fromFailure(all, state.reportedFailure(), state.mode, state.encoding));
190
- }
191
- }
101
+ * Parses a stream of chunks incrementally, as one input. Chunks are parsed
102
+ * as they arrive, in partial mode; when the parser runs out of input, its
103
+ * repetitions keep checkpoints (see `internal/resume.ts`), so the next
104
+ * attempt carries on from where the last one stopped instead of starting
105
+ * over.
106
+ */
107
+ var Incremental = class {
108
+ parser;
109
+ context;
110
+ kind;
111
+ text = "";
112
+ bytes = /* @__PURE__ */ new Uint8Array(0);
113
+ items = [];
114
+ length = 0;
115
+ resume = /* @__PURE__ */ new Map();
116
+ /** The input length at the last attempt, and where that attempt ran out of input. */
117
+ attempted = 0;
118
+ restart = 0;
119
+ /** Set once an attempt settles: a success (with its end offset) or a definite failure. */
120
+ settled;
121
+ constructor(parser, context, empty) {
122
+ this.parser = parser;
123
+ this.context = context;
124
+ if (empty !== void 0) this.append(empty);
125
+ }
126
+ append(chunk) {
127
+ if (Predicate.isString(chunk)) {
128
+ this.kind ??= 0;
129
+ this.text += chunk;
130
+ this.length += chunk.length;
131
+ } else if (chunk instanceof Uint8Array) {
132
+ this.kind ??= 1;
133
+ const needed = this.length + chunk.length;
134
+ if (needed > this.bytes.length) {
135
+ const grown = new Uint8Array(Math.max(needed, this.bytes.length * 2, 4096));
136
+ grown.set(this.bytes.subarray(0, this.length));
137
+ this.bytes = grown;
138
+ }
139
+ this.bytes.set(chunk, this.length);
140
+ this.length = needed;
141
+ } else {
142
+ this.kind ??= 2;
143
+ for (let i = 0; i < chunk.length; i++) this.items.push(chunk[i]);
144
+ this.length = this.items.length;
145
+ }
146
+ }
147
+ input() {
148
+ switch (this.kind) {
149
+ case 1: return this.bytes.subarray(0, this.length);
150
+ case 2: return this.items;
151
+ default: return this.text;
152
+ }
153
+ }
154
+ push(chunk) {
155
+ if (chunk.length === 0) return;
156
+ this.append(chunk);
157
+ if (this.settled !== void 0) return;
158
+ const added = this.length - this.attempted;
159
+ if (added < (this.attempted - this.restart) / 2) return;
160
+ if (this.kind === 0 && added < this.attempted / 8) return;
161
+ this.attempt();
162
+ }
163
+ /** The step attempts run: the parser's resumable compiled code if it was compiled, else the interpreter. */
164
+ step(state) {
165
+ return Stack.run(Registry.stepFor(this.parser, state, true) ?? this.parser.step, state);
166
+ }
167
+ attempt() {
168
+ const state = new State(this.input(), {
169
+ partial: true,
170
+ context: this.context
171
+ });
172
+ state.resume = this.resume;
173
+ const a = this.step(state);
174
+ this.attempted = this.length;
175
+ if (a !== Fail) this.settled = {
176
+ value: a,
177
+ pos: state.pos
178
+ };
179
+ else if (state.mode === "Incomplete") this.restart = state.failure.offset;
180
+ else this.settled = "failed";
181
+ }
182
+ finish() {
183
+ const settled = this.settled;
184
+ if (settled !== void 0 && settled !== "failed") {
185
+ if (settled.pos === this.length) return Effect.succeed(settled.value);
186
+ } else if (settled === void 0) {
187
+ const state = new State(this.input(), { context: this.context });
188
+ state.resume = this.resume;
189
+ const a = this.step(state);
190
+ if (a !== Fail && state.pos === state.end) return Effect.succeed(a);
191
+ }
192
+ const all = this.input();
193
+ const state = new State(all, { context: this.context });
194
+ const a = Stack.run(this.parser.step, state);
195
+ if (a !== Fail && state.pos === state.end) return Effect.succeed(a);
196
+ if (a !== Fail) state.backtrack("Eof", ["end of input"]);
197
+ return Effect.fail(ParseError.fromFailure(all, state.reportedFailure(), state.mode, state.encoding));
198
+ }
199
+ };
192
200
  /**
193
- * Parses an entire stream of chunks as a single complete input.
194
- *
195
- * Parsing does not wait for the stream to end: each chunk is parsed as it
196
- * arrives, in partial mode, and when the parser runs out of input its
197
- * repetitions (`repeat`, `separated`, `fold`, `escaped`, ...) remember how
198
- * far they got, so that the next attempt resumes there rather than starting
199
- * over. A large document, such as the body of a `fetch` response, is
200
- * therefore parsed while it downloads, and is ready soon after its last
201
- * byte. Use {@link parseReadable} or {@link parseResponse} for web streams.
202
- *
203
- * The result and any `ParseError` are those of parsing the whole input at
204
- * once: errors are reported once the stream has ended, by an ordinary
205
- * interpreted parse of the whole input. A parser compiled with
206
- * `Parser.compile` streams compiled too (with a build that handles partial
207
- * input), which is several times faster. As with compiled parsers,
208
- * callbacks should be pure: the elements parsed before a checkpoint are
209
- * not parsed again, and on failure everything is parsed again.
210
- *
211
- * @since 0.1.0
212
- * @category combinators
213
- */
214
- export const parseAll = dual((args) => Stream.isStream(args[0]), (self, parser, options) => Effect.flatMap(Effect.context(), (context) => Effect.suspend(() => {
215
- const empty = options?.empty === undefined ? undefined : fromSource(options.empty);
216
- const incremental = new Incremental(parser, context, empty);
217
- return Effect.flatMap(Stream.runForEach(self, (chunk) => Effect.sync(() => incremental.push(fromSource(chunk)))), () => Effect.suspend(() => incremental.finish()));
201
+ * Parses an entire stream of chunks as a single complete input.
202
+ *
203
+ * Parsing does not wait for the stream to end: each chunk is parsed as it
204
+ * arrives, in partial mode, and when the parser runs out of input its
205
+ * repetitions (`repeat`, `separated`, `fold`, `escaped`, ...) remember how
206
+ * far they got, so that the next attempt resumes there rather than starting
207
+ * over. A large document, such as the body of a `fetch` response, is
208
+ * therefore parsed while it downloads, and is ready soon after its last
209
+ * byte. Use {@link parseReadable} or {@link parseResponse} for web streams.
210
+ *
211
+ * The result and any `ParseError` are those of parsing the whole input at
212
+ * once: errors are reported once the stream has ended, by an ordinary
213
+ * interpreted parse of the whole input. A parser compiled with the
214
+ * `Compiler` module streams compiled too (with a build that handles partial
215
+ * input), which is several times faster. As with compiled parsers,
216
+ * callbacks should be pure: the elements parsed before a checkpoint are
217
+ * not parsed again, and on failure everything is parsed again.
218
+ *
219
+ * @since 0.1.0
220
+ * @category combinators
221
+ */
222
+ const parseAll = /*#__PURE__*/ dual((args) => Stream.isStream(args[0]), (self, parser, options) => Effect.flatMap(Effect.context(), (context) => Effect.suspend(() => {
223
+ const incremental = new Incremental(parser, context, options?.empty === void 0 ? void 0 : fromSource(options.empty));
224
+ return Effect.flatMap(Stream.runForEach(self, (chunk) => Effect.sync(() => incremental.push(fromSource(chunk)))), () => Effect.suspend(() => incremental.finish()));
218
225
  })));
219
226
  /**
220
- * An error reading a `ReadableStream` given to {@link parseReadable} or
221
- * {@link parseResponse}.
222
- *
223
- * @since 0.1.0
224
- * @category errors
225
- */
226
- export class ReadError extends Data.TaggedError("ReadError") {
227
- }
227
+ * An error reading a `ReadableStream` given to {@link parseReadable} or
228
+ * {@link parseResponse}.
229
+ *
230
+ * @since 0.1.0
231
+ * @category errors
232
+ */
233
+ var ReadError = class extends (/*#__PURE__*/ Data.TaggedError("ReadError")) {};
228
234
  /**
229
- * Parses a web `ReadableStream` of bytes, such as the body of a `fetch`
230
- * response, incrementally (see {@link parseAll}): the bytes are parsed as
231
- * they arrive, without waiting for the end of the stream or decoding them
232
- * first. Use a byte parser, e.g. one built from `Text.utf8`.
233
- *
234
- * @example
235
- * ```ts
236
- * import { Effect } from "effect"
237
- * import { Parser, ParserStream, Text } from "@thomasfosterau/effect-parse"
238
- *
239
- * const csvLine = Parser.separated(Text.utf8.takeTill(",\n"), Text.utf8.literal(","))
240
- * const csv = Parser.separated(csvLine, Text.utf8.literal("\n"))
241
- *
242
- * const response = await fetch("https://example.com/data.csv")
243
- * const rows = await Effect.runPromise(ParserStream.parseReadable(response.body!, csv))
244
- * ```
245
- *
246
- * @since 0.1.0
247
- * @category combinators
248
- */
249
- export const parseReadable = dual(2, (self, parser) => parseAll(Stream.fromReadableStream({ evaluate: () => self, onError: (cause) => new ReadError({ cause }) }), parser, { empty: new Uint8Array(0) }));
235
+ * Parses a web `ReadableStream` of bytes, such as the body of a `fetch`
236
+ * response, incrementally (see {@link parseAll}): the bytes are parsed as
237
+ * they arrive, without waiting for the end of the stream or decoding them
238
+ * first. Use a byte parser, e.g. one built from `Text.utf8`.
239
+ *
240
+ * @example
241
+ * ```ts
242
+ * import { Effect } from "effect"
243
+ * import { Parser, ParserStream, Text } from "@thomasfosterau/effect-parse"
244
+ *
245
+ * const csvLine = Parser.separated(Text.utf8.takeTill(",\n"), Text.utf8.literal(","))
246
+ * const csv = Parser.separated(csvLine, Text.utf8.literal("\n"))
247
+ *
248
+ * const response = await fetch("https://example.com/data.csv")
249
+ * const rows = await Effect.runPromise(ParserStream.parseReadable(response.body!, csv))
250
+ * ```
251
+ *
252
+ * @since 0.1.0
253
+ * @category combinators
254
+ */
255
+ const parseReadable = /*#__PURE__*/ dual(2, (self, parser) => parseAll(Stream.fromReadableStream({
256
+ evaluate: () => self,
257
+ onError: (cause) => new ReadError({ cause })
258
+ }), parser, { empty: /* @__PURE__ */ new Uint8Array(0) }));
250
259
  /**
251
- * Parses the body of a `fetch` `Response` incrementally, as it downloads
252
- * (see {@link parseReadable}). A response without a body is parsed as empty
253
- * input. The status is not checked.
254
- *
255
- * @example
256
- * ```ts
257
- * import { Effect } from "effect"
258
- * import { Parser, ParserStream, Text } from "@thomasfosterau/effect-parse"
259
- *
260
- * const lines = Parser.separated(Text.utf8.tillLineEnding, Text.utf8.lineEnding)
261
- *
262
- * const response = await fetch("https://example.com/log.txt")
263
- * const value = await Effect.runPromise(ParserStream.parseResponse(response, lines))
264
- * ```
265
- *
266
- * @since 0.1.0
267
- * @category combinators
268
- */
269
- export const parseResponse = dual(2, (self, parser) => parseReadable(self.body ?? new ReadableStream({ start: (c) => c.close() }), parser));
260
+ * Parses the body of a `fetch` `Response` incrementally, as it downloads
261
+ * (see {@link parseReadable}). A response without a body is parsed as empty
262
+ * input. The status is not checked.
263
+ *
264
+ * @example
265
+ * ```ts
266
+ * import { Effect } from "effect"
267
+ * import { Parser, ParserStream, Text } from "@thomasfosterau/effect-parse"
268
+ *
269
+ * const lines = Parser.separated(Text.utf8.tillLineEnding, Text.utf8.lineEnding)
270
+ *
271
+ * const response = await fetch("https://example.com/log.txt")
272
+ * const value = await Effect.runPromise(ParserStream.parseResponse(response, lines))
273
+ * ```
274
+ *
275
+ * @since 0.1.0
276
+ * @category combinators
277
+ */
278
+ const parseResponse = /*#__PURE__*/ dual(2, (self, parser) => parseReadable(self.body ?? new ReadableStream({ start: (c) => c.close() }), parser));
279
+ //#endregion
280
+ export { ReadError, parseAll, parseMany, parseReadable, parseResponse };
281
+
270
282
  //# sourceMappingURL=ParserStream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ParserStream.js","sourceRoot":"","sources":["../src/ParserStream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ParserStream.js","names":[],"sources":["../src/ParserStream.ts"],"sourcesContent":["/**\n * Running parsers over Effect `Stream`s of input chunks.\n *\n * This is where nom's and winnow's *partial* (streaming) parsing meets\n * Effect: chunks are buffered and the parser runs in partial mode, so a\n * value split across chunk boundaries is reported as `Incomplete` and\n * retried once more data arrives. When the stream ends, the leftover input\n * is parsed in complete mode.\n *\n * @example\n * ```ts\n * import { Effect, Stream } from \"effect\"\n * import { Ascii, Parser, ParserStream, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const line = Parser.terminated(Ascii.decInt, Token.literal(\"\\n\"))\n *\n * const program = Stream.make(\"1\\n2\", \"3\\n\", \"4\\n\").pipe(\n * ParserStream.parseMany(line),\n * Stream.runCollect\n * )\n * // Effect.runSync(program) => [1, 23, 4]\n * ```\n *\n * @since 0.1.0\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type * as Context from \"effect/Context\"\nimport * as Data from \"effect/Data\"\nimport * as Effect from \"effect/Effect\"\nimport { dual } from \"effect/Function\"\nimport * as Stream from \"effect/Stream\"\nimport type { BinaryInput, Input, Source } from \"./Input.js\"\nimport { Fail, Failure, fromSource, State } from \"./Input.js\"\nimport * as ParseError from \"./ParseError.js\"\nimport * as Registry from \"./internal/compiler/registry.js\"\nimport type * as Resume from \"./internal/resume.js\"\nimport * as Run from \"./internal/run.js\"\nimport * as Stack from \"./internal/stack.js\"\nimport type { Parser } from \"./Parser.js\"\n\n/**\n * Input kinds that can be streamed in chunks.\n *\n * @since 0.1.0\n * @category models\n */\nexport type Chunkable = string | Uint8Array | ReadonlyArray<unknown>\n\nconst concat = <I extends Chunkable>(a: I, b: I): I => {\n if (Predicate.isString(a)) return (a + (b as string)) as I\n if (a instanceof Uint8Array) {\n if (a.length === 0) return b\n const out = new Uint8Array(a.length + (b as Uint8Array).length)\n out.set(a)\n out.set(b as Uint8Array, a.length)\n return out as I\n }\n return [...a, ...(b as ReadonlyArray<unknown>)] as unknown as I\n}\n\nconst sliceFrom = <I extends Chunkable>(input: I, offset: number): I =>\n (Predicate.isString(input) ? input.slice(offset) : input.slice(offset)) as I\n\nconst noProgress = (input: Input, offset: number) =>\n ParseError.fromFailure<never>(\n input,\n new Failure(offset, \"Assert\", [], [], false, undefined, \"`parseMany` parsers must always consume\", 0),\n \"Cut\"\n )\n\n/**\n * Options for {@link parseMany}.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface ParseManyOptions<I> {\n /** The empty input, used to initialise the buffer (inferred from the first chunk if omitted). */\n readonly empty?: Source<I> | undefined\n}\n\n/**\n * Transforms a stream of input chunks into a stream of parsed values by\n * applying `parser` repeatedly. Each application must consume input.\n *\n * Services required by the parser are taken from the stream's context.\n * Error offsets are relative to the internal buffer of unconsumed input,\n * which is also the `input` of the reported `ParseError`.\n *\n * A parser compiled with the `Compiler` module runs compiled, with the\n * build that handles partial input (see `Parser.run`); a value that fails\n * or needs more input is parsed again interpreted, so errors and\n * `Incomplete` are the interpreter's.\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const parseMany: {\n <A, E, R, I extends Chunkable>(\n parser: Parser<A, E, R, I>,\n options?: ParseManyOptions<I>\n ): <E0, R0>(self: Stream.Stream<Source<I>, E0, R0>) => Stream.Stream<A, E0 | ParseError.ParseError<E>, R0 | R>\n <I extends Chunkable, E0, R0, A, E, R>(\n self: Stream.Stream<Source<NoInfer<I>>, E0, R0>,\n parser: Parser<A, E, R, I>,\n options?: ParseManyOptions<I>\n ): Stream.Stream<A, E0 | ParseError.ParseError<E>, R0 | R>\n} = /*#__PURE__*/ dual(\n (args) => Stream.isStream(args[0]),\n <I extends Chunkable, E0, R0, A, E, R>(\n self: Stream.Stream<Source<I>, E0, R0>,\n parser: Parser<A, E, R, I>,\n options?: ParseManyOptions<I>\n ): Stream.Stream<A, E0 | ParseError.ParseError<E>, R0 | R> =>\n Stream.suspend(() => {\n const step = parser.step\n let buffer: I | undefined = options?.empty === undefined ? undefined : fromSource<I>(options.empty)\n\n const drain = (context: any, partial: boolean): Effect.Effect<Array<A>, ParseError.ParseError<E>> => {\n const out: Array<A> = []\n if (buffer === undefined) return Effect.succeed(out)\n const input = buffer\n // One state for the whole buffer, reset before each value\n const state = new State(input)\n let offset = 0\n while (offset < input.length) {\n state.reset(offset, { partial, context })\n const a = Run.runOn(parser, step, state)\n if (a === Fail) {\n if (partial && state.mode === \"Incomplete\") break\n return Effect.fail(ParseError.fromFailure<E>(input, state.reportedFailure(), state.mode, state.encoding))\n }\n if (state.pos === offset) return Effect.fail(noProgress(input, offset))\n out.push(a)\n offset = state.pos\n }\n buffer = sliceFrom(input, offset)\n return Effect.succeed(out)\n }\n\n const feed = (source: Source<I>) =>\n Effect.flatMap(Effect.context<R>(), (context) =>\n Effect.suspend(() => {\n const chunk = fromSource<I>(source)\n buffer = buffer === undefined ? chunk : concat(buffer, chunk)\n return drain(context, true)\n })\n )\n\n const finish = Effect.flatMap(Effect.context<R>(), (context) => Effect.suspend(() => drain(context, false)))\n\n return self.pipe(\n Stream.mapEffect(feed),\n Stream.flattenIterable,\n Stream.concat(Stream.unwrap(Effect.map(finish, Stream.fromIterable)))\n )\n })\n)\n\n/**\n * Parses a stream of chunks incrementally, as one input. Chunks are parsed\n * as they arrive, in partial mode; when the parser runs out of input, its\n * repetitions keep checkpoints (see `internal/resume.ts`), so the next\n * attempt carries on from where the last one stopped instead of starting\n * over.\n */\nclass Incremental<A, E, I extends Chunkable> {\n private kind: 0 | 1 | 2 | undefined\n private text = \"\"\n private bytes = new Uint8Array(0)\n private items: Array<unknown> = []\n private length = 0\n private readonly resume: Resume.Checkpoints = new Map()\n /** The input length at the last attempt, and where that attempt ran out of input. */\n private attempted = 0\n private restart = 0\n /** Set once an attempt settles: a success (with its end offset) or a definite failure. */\n private settled: { readonly value: A; readonly pos: number } | \"failed\" | undefined\n\n constructor(\n private readonly parser: Parser<A, E, any, I>,\n private readonly context: Context.Context<never>,\n empty: I | undefined\n ) {\n if (empty !== undefined) this.append(empty)\n }\n\n private append(chunk: I): void {\n if (Predicate.isString(chunk)) {\n this.kind ??= 0\n this.text += chunk\n this.length += chunk.length\n } else if (chunk instanceof Uint8Array) {\n this.kind ??= 1\n const needed = this.length + chunk.length\n if (needed > this.bytes.length) {\n // Grow geometrically, so appending costs amortized constant time per byte\n const grown = new Uint8Array(Math.max(needed, this.bytes.length * 2, 4096))\n grown.set(this.bytes.subarray(0, this.length))\n this.bytes = grown\n }\n this.bytes.set(chunk, this.length)\n this.length = needed\n } else {\n this.kind ??= 2\n for (let i = 0; i < chunk.length; i++) this.items.push(chunk[i])\n this.length = this.items.length\n }\n }\n\n private input(): I {\n switch (this.kind) {\n case 1:\n return this.bytes.subarray(0, this.length) as I\n case 2:\n // Items are only appended between attempts, after each state has read its `end`\n return this.items as unknown as I\n default:\n return this.text as I\n }\n }\n\n push(chunk: I): void {\n if (chunk.length === 0) return\n this.append(chunk)\n if (this.settled !== undefined) return\n // An attempt re-reads what the last one could not finish, from `restart`;\n // waiting until at least half as much new input has arrived keeps the\n // total work linear in the input. Strings are also copied when they are\n // flattened, so they wait for a fraction of the whole input too.\n const added = this.length - this.attempted\n if (added < (this.attempted - this.restart) / 2) return\n if (this.kind === 0 && added < this.attempted / 8) return\n this.attempt()\n }\n\n /** The step attempts run: the parser's resumable compiled code if it was compiled, else the interpreter. */\n private step(state: State<I>): unknown {\n return Stack.run(Registry.stepFor(this.parser, state, true) ?? this.parser.step, state)\n }\n\n private attempt(): void {\n const state = new State(this.input(), { partial: true, context: this.context })\n state.resume = this.resume\n const a = this.step(state)\n this.attempted = this.length\n if (a !== Fail) {\n this.settled = { value: a as A, pos: state.pos }\n } else if (state.mode === \"Incomplete\") {\n this.restart = state.failure.offset\n } else {\n this.settled = \"failed\"\n }\n }\n\n finish(): Effect.Effect<A, ParseError.ParseError<E>> {\n const settled = this.settled\n if (settled !== undefined && settled !== \"failed\") {\n if (settled.pos === this.length) return Effect.succeed(settled.value)\n } else if (settled === undefined) {\n // The last attempt, in complete mode, resumes from the checkpoints too\n const state = new State(this.input(), { context: this.context })\n state.resume = this.resume\n const a = this.step(state)\n if (a !== Fail && state.pos === state.end) return Effect.succeed(a as A)\n }\n // The error comes from an ordinary parse of the whole input, so it is the\n // same as if the input had been parsed in one go\n const all = this.input()\n const state = new State(all, { context: this.context })\n const a = Stack.run(this.parser.step, state)\n if (a !== Fail && state.pos === state.end) return Effect.succeed(a)\n if (a !== Fail) state.backtrack(\"Eof\", [\"end of input\"])\n return Effect.fail(ParseError.fromFailure<E>(all, state.reportedFailure(), state.mode, state.encoding))\n }\n}\n\n/**\n * Parses an entire stream of chunks as a single complete input.\n *\n * Parsing does not wait for the stream to end: each chunk is parsed as it\n * arrives, in partial mode, and when the parser runs out of input its\n * repetitions (`repeat`, `separated`, `fold`, `escaped`, ...) remember how\n * far they got, so that the next attempt resumes there rather than starting\n * over. A large document, such as the body of a `fetch` response, is\n * therefore parsed while it downloads, and is ready soon after its last\n * byte. Use {@link parseReadable} or {@link parseResponse} for web streams.\n *\n * The result and any `ParseError` are those of parsing the whole input at\n * once: errors are reported once the stream has ended, by an ordinary\n * interpreted parse of the whole input. A parser compiled with the\n * `Compiler` module streams compiled too (with a build that handles partial\n * input), which is several times faster. As with compiled parsers,\n * callbacks should be pure: the elements parsed before a checkpoint are\n * not parsed again, and on failure everything is parsed again.\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const parseAll: {\n <A, E, R, I extends Chunkable>(\n parser: Parser<A, E, R, I>,\n options?: ParseManyOptions<I>\n ): <E0, R0>(self: Stream.Stream<Source<I>, E0, R0>) => Effect.Effect<A, E0 | ParseError.ParseError<E>, R0 | R>\n <I extends Chunkable, E0, R0, A, E, R>(\n self: Stream.Stream<Source<NoInfer<I>>, E0, R0>,\n parser: Parser<A, E, R, I>,\n options?: ParseManyOptions<I>\n ): Effect.Effect<A, E0 | ParseError.ParseError<E>, R0 | R>\n} = /*#__PURE__*/ dual(\n (args) => Stream.isStream(args[0]),\n <I extends Chunkable, E0, R0, A, E, R>(\n self: Stream.Stream<Source<I>, E0, R0>,\n parser: Parser<A, E, R, I>,\n options?: ParseManyOptions<I>\n ): Effect.Effect<A, E0 | ParseError.ParseError<E>, R0 | R> =>\n Effect.flatMap(Effect.context<R>(), (context) =>\n Effect.suspend(() => {\n const empty = options?.empty === undefined ? undefined : fromSource<I>(options.empty)\n const incremental = new Incremental(parser, context as Context.Context<never>, empty)\n return Effect.flatMap(\n Stream.runForEach(self, (chunk) => Effect.sync(() => incremental.push(fromSource<I>(chunk)))),\n () => Effect.suspend(() => incremental.finish())\n )\n })\n )\n)\n\n/**\n * An error reading a `ReadableStream` given to {@link parseReadable} or\n * {@link parseResponse}.\n *\n * @since 0.1.0\n * @category errors\n */\nexport class ReadError extends /*#__PURE__*/ Data.TaggedError(\"ReadError\")<{ readonly cause: unknown }> {}\n\n/**\n * Parses a web `ReadableStream` of bytes, such as the body of a `fetch`\n * response, incrementally (see {@link parseAll}): the bytes are parsed as\n * they arrive, without waiting for the end of the stream or decoding them\n * first. Use a byte parser, e.g. one built from `Text.utf8`.\n *\n * @example\n * ```ts\n * import { Effect } from \"effect\"\n * import { Parser, ParserStream, Text } from \"@thomasfosterau/effect-parse\"\n *\n * const csvLine = Parser.separated(Text.utf8.takeTill(\",\\n\"), Text.utf8.literal(\",\"))\n * const csv = Parser.separated(csvLine, Text.utf8.literal(\"\\n\"))\n *\n * const response = await fetch(\"https://example.com/data.csv\")\n * const rows = await Effect.runPromise(ParserStream.parseReadable(response.body!, csv))\n * ```\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const parseReadable: {\n <A, E, R>(\n parser: Parser<A, E, R, Uint8Array>\n ): (self: ReadableStream<BinaryInput>) => Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>\n <A, E, R>(\n self: ReadableStream<BinaryInput>,\n parser: Parser<A, E, R, Uint8Array>\n ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>\n} = /*#__PURE__*/ dual(\n 2,\n <A, E, R>(\n self: ReadableStream<BinaryInput>,\n parser: Parser<A, E, R, Uint8Array>\n ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R> =>\n parseAll(\n Stream.fromReadableStream({ evaluate: () => self, onError: (cause) => new ReadError({ cause }) }),\n parser,\n { empty: new Uint8Array(0) }\n )\n)\n\n/**\n * Parses the body of a `fetch` `Response` incrementally, as it downloads\n * (see {@link parseReadable}). A response without a body is parsed as empty\n * input. The status is not checked.\n *\n * @example\n * ```ts\n * import { Effect } from \"effect\"\n * import { Parser, ParserStream, Text } from \"@thomasfosterau/effect-parse\"\n *\n * const lines = Parser.separated(Text.utf8.tillLineEnding, Text.utf8.lineEnding)\n *\n * const response = await fetch(\"https://example.com/log.txt\")\n * const value = await Effect.runPromise(ParserStream.parseResponse(response, lines))\n * ```\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const parseResponse: {\n <A, E, R>(\n parser: Parser<A, E, R, Uint8Array>\n ): (self: Response) => Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>\n <A, E, R>(\n self: Response,\n parser: Parser<A, E, R, Uint8Array>\n ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>\n} = /*#__PURE__*/ dual(\n 2,\n <A, E, R>(\n self: Response,\n parser: Parser<A, E, R, Uint8Array>\n ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R> =>\n parseReadable(self.body ?? new ReadableStream<Uint8Array>({ start: (c) => c.close() }), parser)\n)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,MAAM,UAA+B,GAAM,MAAY;CACrD,IAAI,UAAU,SAAS,CAAC,GAAG,OAAQ,IAAK;CACxC,IAAI,aAAa,YAAY;EAC3B,IAAI,EAAE,WAAW,GAAG,OAAO;EAC3B,MAAM,MAAM,IAAI,WAAW,EAAE,SAAU,EAAiB,MAAM;EAC9D,IAAI,IAAI,CAAC;EACT,IAAI,IAAI,GAAiB,EAAE,MAAM;EACjC,OAAO;CACT;CACA,OAAO,CAAC,GAAG,GAAG,GAAI,CAA4B;AAChD;AAEA,MAAM,aAAkC,OAAU,WAC/C,UAAU,SAAS,KAAK,IAAI,MAAM,MAAM,MAAM,IAAI,MAAM,MAAM,MAAM;AAEvE,MAAM,cAAc,OAAc,WAChC,WAAW,YACT,OACA,IAAI,QAAQ,QAAQ,UAAU,CAAC,GAAG,CAAC,GAAG,OAAO,KAAA,GAAW,2CAA2C,CAAC,GACpG,KACF;;;;;;;;;;;;;;;;;AA6BF,MAAa,YAUK,oBACf,SAAS,OAAO,SAAS,KAAK,EAAE,IAE/B,MACA,QACA,YAEA,OAAO,cAAc;CACnB,MAAM,OAAO,OAAO;CACpB,IAAI,SAAwB,SAAS,UAAU,KAAA,IAAY,KAAA,IAAY,WAAc,QAAQ,KAAK;CAElG,MAAM,SAAS,SAAc,YAAwE;EACnG,MAAM,MAAgB,CAAC;EACvB,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO,QAAQ,GAAG;EACnD,MAAM,QAAQ;EAEd,MAAM,QAAQ,IAAI,MAAM,KAAK;EAC7B,IAAI,SAAS;EACb,OAAO,SAAS,MAAM,QAAQ;GAC5B,MAAM,MAAM,QAAQ;IAAE;IAAS;GAAQ,CAAC;GACxC,MAAM,IAAI,IAAI,MAAM,QAAQ,MAAM,KAAK;GACvC,IAAI,MAAM,MAAM;IACd,IAAI,WAAW,MAAM,SAAS,cAAc;IAC5C,OAAO,OAAO,KAAK,WAAW,YAAe,OAAO,MAAM,gBAAgB,GAAG,MAAM,MAAM,MAAM,QAAQ,CAAC;GAC1G;GACA,IAAI,MAAM,QAAQ,QAAQ,OAAO,OAAO,KAAK,WAAW,OAAO,MAAM,CAAC;GACtE,IAAI,KAAK,CAAC;GACV,SAAS,MAAM;EACjB;EACA,SAAS,UAAU,OAAO,MAAM;EAChC,OAAO,OAAO,QAAQ,GAAG;CAC3B;CAEA,MAAM,QAAQ,WACZ,OAAO,QAAQ,OAAO,QAAW,IAAI,YACnC,OAAO,cAAc;EACnB,MAAM,QAAQ,WAAc,MAAM;EAClC,SAAS,WAAW,KAAA,IAAY,QAAQ,OAAO,QAAQ,KAAK;EAC5D,OAAO,MAAM,SAAS,IAAI;CAC5B,CAAC,CACH;CAEF,MAAM,SAAS,OAAO,QAAQ,OAAO,QAAW,IAAI,YAAY,OAAO,cAAc,MAAM,SAAS,KAAK,CAAC,CAAC;CAE3G,OAAO,KAAK,KACV,OAAO,UAAU,IAAI,GACrB,OAAO,iBACP,OAAO,OAAO,OAAO,OAAO,OAAO,IAAI,QAAQ,OAAO,YAAY,CAAC,CAAC,CACtE;AACF,CAAC,CACL;;;;;;;;AASA,IAAM,cAAN,MAA6C;CAcxB;CACA;CAdnB;CACA,OAAe;CACf,wBAAgB,IAAI,WAAW,CAAC;CAChC,QAAgC,CAAC;CACjC,SAAiB;CACjB,yBAA8C,IAAI,IAAI;;CAEtD,YAAoB;CACpB,UAAkB;;CAElB;CAEA,YACE,QACA,SACA,OACA;EAHiB,KAAA,SAAA;EACA,KAAA,UAAA;EAGjB,IAAI,UAAU,KAAA,GAAW,KAAK,OAAO,KAAK;CAC5C;CAEA,OAAe,OAAgB;EAC7B,IAAI,UAAU,SAAS,KAAK,GAAG;GAC7B,KAAK,SAAS;GACd,KAAK,QAAQ;GACb,KAAK,UAAU,MAAM;EACvB,OAAO,IAAI,iBAAiB,YAAY;GACtC,KAAK,SAAS;GACd,MAAM,SAAS,KAAK,SAAS,MAAM;GACnC,IAAI,SAAS,KAAK,MAAM,QAAQ;IAE9B,MAAM,QAAQ,IAAI,WAAW,KAAK,IAAI,QAAQ,KAAK,MAAM,SAAS,GAAG,IAAI,CAAC;IAC1E,MAAM,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,CAAC;IAC7C,KAAK,QAAQ;GACf;GACA,KAAK,MAAM,IAAI,OAAO,KAAK,MAAM;GACjC,KAAK,SAAS;EAChB,OAAO;GACL,KAAK,SAAS;GACd,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,MAAM,EAAE;GAC/D,KAAK,SAAS,KAAK,MAAM;EAC3B;CACF;CAEA,QAAmB;EACjB,QAAQ,KAAK,MAAb;GACE,KAAK,GACH,OAAO,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM;GAC3C,KAAK,GAEH,OAAO,KAAK;GACd,SACE,OAAO,KAAK;EAChB;CACF;CAEA,KAAK,OAAgB;EACnB,IAAI,MAAM,WAAW,GAAG;EACxB,KAAK,OAAO,KAAK;EACjB,IAAI,KAAK,YAAY,KAAA,GAAW;EAKhC,MAAM,QAAQ,KAAK,SAAS,KAAK;EACjC,IAAI,SAAS,KAAK,YAAY,KAAK,WAAW,GAAG;EACjD,IAAI,KAAK,SAAS,KAAK,QAAQ,KAAK,YAAY,GAAG;EACnD,KAAK,QAAQ;CACf;;CAGA,KAAa,OAA0B;EACrC,OAAO,MAAM,IAAI,SAAS,QAAQ,KAAK,QAAQ,OAAO,IAAI,KAAK,KAAK,OAAO,MAAM,KAAK;CACxF;CAEA,UAAwB;EACtB,MAAM,QAAQ,IAAI,MAAM,KAAK,MAAM,GAAG;GAAE,SAAS;GAAM,SAAS,KAAK;EAAQ,CAAC;EAC9E,MAAM,SAAS,KAAK;EACpB,MAAM,IAAI,KAAK,KAAK,KAAK;EACzB,KAAK,YAAY,KAAK;EACtB,IAAI,MAAM,MACR,KAAK,UAAU;GAAE,OAAO;GAAQ,KAAK,MAAM;EAAI;OAC1C,IAAI,MAAM,SAAS,cACxB,KAAK,UAAU,MAAM,QAAQ;OAE7B,KAAK,UAAU;CAEnB;CAEA,SAAqD;EACnD,MAAM,UAAU,KAAK;EACrB,IAAI,YAAY,KAAA,KAAa,YAAY,UACnC;OAAA,QAAQ,QAAQ,KAAK,QAAQ,OAAO,OAAO,QAAQ,QAAQ,KAAK;EAAA,OAC/D,IAAI,YAAY,KAAA,GAAW;GAEhC,MAAM,QAAQ,IAAI,MAAM,KAAK,MAAM,GAAG,EAAE,SAAS,KAAK,QAAQ,CAAC;GAC/D,MAAM,SAAS,KAAK;GACpB,MAAM,IAAI,KAAK,KAAK,KAAK;GACzB,IAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,OAAO,OAAO,QAAQ,CAAM;EACzE;EAGA,MAAM,MAAM,KAAK,MAAM;EACvB,MAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,SAAS,KAAK,QAAQ,CAAC;EACtD,MAAM,IAAI,MAAM,IAAI,KAAK,OAAO,MAAM,KAAK;EAC3C,IAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,OAAO,OAAO,QAAQ,CAAC;EAClE,IAAI,MAAM,MAAM,MAAM,UAAU,OAAO,CAAC,cAAc,CAAC;EACvD,OAAO,OAAO,KAAK,WAAW,YAAe,KAAK,MAAM,gBAAgB,GAAG,MAAM,MAAM,MAAM,QAAQ,CAAC;CACxG;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,WAUK,oBACf,SAAS,OAAO,SAAS,KAAK,EAAE,IAE/B,MACA,QACA,YAEA,OAAO,QAAQ,OAAO,QAAW,IAAI,YACnC,OAAO,cAAc;CAEnB,MAAM,cAAc,IAAI,YAAY,QAAQ,SAD9B,SAAS,UAAU,KAAA,IAAY,KAAA,IAAY,WAAc,QAAQ,KAAK,CACA;CACpF,OAAO,OAAO,QACZ,OAAO,WAAW,OAAO,UAAU,OAAO,WAAW,YAAY,KAAK,WAAc,KAAK,CAAC,CAAC,CAAC,SACtF,OAAO,cAAc,YAAY,OAAO,CAAC,CACjD;AACF,CAAC,CACH,CACJ;;;;;;;;AASA,IAAa,YAAb,eAA6C,mBAAK,YAAY,WAAW,EAAA,CAA+B,CAAC;;;;;;;;;;;;;;;;;;;;;;AAuBzG,MAAa,gBAQK,mBAChB,IAEE,MACA,WAEA,SACE,OAAO,mBAAmB;CAAE,gBAAgB;CAAM,UAAU,UAAU,IAAI,UAAU,EAAE,MAAM,CAAC;AAAE,CAAC,GAChG,QACA,EAAE,uBAAO,IAAI,WAAW,CAAC,EAAE,CAC7B,CACJ;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,gBAQK,mBAChB,IAEE,MACA,WAEA,cAAc,KAAK,QAAQ,IAAI,eAA2B,EAAE,QAAQ,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAClG"}