src/Manifest.bend

mylsm-lsm-store@0.4.0.0 · 605 lines · 0 definitions

1import Base
2import mylsm-lsm-store@0.4.0.0/src/StorageBytes.bend as StorageBytes
3import bend-kit-bytes@0.3.2.0/bytes.bend as Bytes
4import mylsm-lsm-store@0.4.0.0/src/hub_sha/sha256.bend as SHA
5
6# Represent Manifest data used by the binary manifest codec.
7type Manifest is Data:
8  M{levels: List<&2, List<&2, String>>}
9
10# Represent Error data used by the binary manifest codec.
11type Error is Data:
12  TooLarge{}
13  InvalidName{}
14
15# Represent ParseState data used by the binary manifest codec.
16type ParseState is Data:
17  ReadNamesCount{levels_left: Nat, levels_acc: List<&2, List<&2, String>>}
18  ReadNameLength{levels_left: Nat, levels_acc: List<&2, List<&2, String>>, names_left: Nat, names_acc: List<&2, String>}
19  ReadNameBody{levels_left: Nat, levels_acc: List<&2, List<&2, String>>, names_left: Nat, names_acc: List<&2, String>}
20
21# Represent ParseInput data used by the binary manifest codec.
22type ParseInput is Type:
23  NoInput{cursor: Bytes.Cursor}
24  NameInput{value: Bytes.Cursor & Maybe<&2, String>}
25
26# Represent ParseTransition data used by the binary manifest codec.
27type ParseTransition is Type:
28  Continue{state: ParseState, input: ParseInput}
29  Reject{cursor: Bytes.Cursor}
30  Finish{cursor: Bytes.Cursor, levels: List<&2, List<&2, String>>}
31
32def magic.result(result: Maybe<&1, Bytes.Bytes>) -> Bytes.Bytes:
33  match result:
34    case Some{bytes}:
35      bytes
36    case None{}:
37      Bytes.new(0)
38
39# Handle magic in the binary manifest codec.
40def magic() -> Bytes.Bytes:
41  magic.result(Bytes.from_hex("4d594c534d334d00"))
42
43# Handle u32 in the binary manifest codec.
44def u32(+value: U32) -> Bytes.Bytes:
45  Bytes.set.u32be(Bytes.new(4), 0, value)
46
47def bytes.clone.pair(+len: U32, copied: Array<U32> & Array<U32>) -> Bytes.Bytes & Bytes.Bytes:
48  match copied:
49    case (left, right):
50      (Bytes.Bytes{len, left}, Bytes.Bytes{len, right})
51
52def bytes.clone.split(bytes: Bytes.Bytes) -> Bytes.Bytes & Bytes.Bytes:
53  match bytes:
54    case Bytes.Bytes{+len, buf}:
55      bytes.clone.pair(len, Bytes.copy.bytes(len, buf, Bytes.alloc(len), 0, 0))
56
57def bytes.clone.first(pair: Bytes.Bytes & Bytes.Bytes) -> Bytes.Bytes:
58  match pair:
59    case (left, _):
60      left
61
62def bytes.length(pair: Bytes.Bytes & U32) -> U32:
63  match pair:
64    case (_, len):
65      len
66
67def bytes.slice.second(pair: Bytes.Bytes & Bytes.Bytes) -> Bytes.Bytes:
68  match pair:
69    case (_, second):
70      second
71
72def encode.name.copies(+len: U32, tail: Bytes.Bytes, copies: Array<U32> & Array<U32>) -> Bytes.Bytes:
73  match copies:
74    case (stored, _unused):
75      Bytes.concat([u32(len), Bytes.Bytes{len, stored}, tail])
76
77def encode.name.buffer(+len: U32, tail: Bytes.Bytes, packed: Bytes.Bytes) -> Bytes.Bytes:
78  match packed:
79    case Bytes.Bytes{_, buf}:
80      encode.name.copies(len, tail, Bytes.copy.bytes(len, buf, Bytes.alloc(len), 0, 0))
81
82def encode.name.copy(pair: Bytes.Bytes & U32, tail: Bytes.Bytes) -> Bytes.Bytes:
83  match pair:
84    case (packed, +len):
85      encode.name.buffer(len, tail, packed)
86
87def encode.name.prefix(result: Result<&1, &1, U32 & String, Bytes.Bytes>, tail: Bytes.Bytes) -> Bytes.Bytes:
88  match result:
89    case Fail{_}:
90      Bytes.concat([u32(0), Bytes.new(0), tail])
91    case Done{encoded}:
92      encode.name.copy(Bytes.length(encoded), tail)
93
94def name.char.valid(+char: Char) -> Bool:
95  +byte = Char.to_u32(char)
96  U32.is_le(48, byte) && U32.is_le(byte, 57) ||
97    U32.is_le(65, byte) && U32.is_le(byte, 90) ||
98    U32.is_le(97, byte) && U32.is_le(byte, 122) ||
99    U32.is_eq(byte, 45) || U32.is_eq(byte, 95) || U32.is_eq(byte, 46) || U32.is_lt(127, byte)
100
101def name.text.valid.chars(text: String, valid: Bool) -> Bool:
102  match text:
103    case SNil{}:
104      valid
105    case SCon{+char, rest}:
106      name.text.valid.chars(rest, valid && name.char.valid(char))
107
108def name.text.valid.edge(text: String, dot_component: Bool) -> Bool:
109  match dot_component:
110    case True{}:
111      False{}
112    case False{}:
113      name.text.valid.chars(text, True{})
114
115def name.text.valid(+text: String) -> Bool:
116  match text:
117    case SNil{}:
118      False{}
119    case SCon{_, _}:
120      name.text.valid.edge(text, String.eq(text, ".") || String.eq(text, ".."))
121
122def names.valid.step(rest: List<&2, String>, valid: Bool) -> Bool:
123  match rest valid:
124    case _ False{}:
125      False{}
126    case Nil{} True{}:
127      True{}
128    case Con{name, tail} True{}:
129      names.valid.step(tail, name.text.valid(name))
130
131def names.valid(names: List<&2, String>) -> Bool:
132  names.valid.step(names, True{})
133
134def levels.valid.step(rest: List<&2, List<&2, String>>, valid: Bool) -> Bool:
135  match rest valid:
136    case _ False{}:
137      False{}
138    case Nil{} True{}:
139      True{}
140    case Con{+names, tail} True{}:
141      levels.valid.step(tail, names.valid(names))
142
143def levels.valid(levels: List<&2, List<&2, String>>) -> Bool:
144  levels.valid.step(levels, True{})
145
146def encode.names(names: List<&2, String>) -> Bytes.Bytes:
147  match names:
148    case Nil{}:
149      Bytes.new(0)
150    case Con{name, rest}:
151      encode.name.prefix(StorageBytes.from_string(name), encode.names(rest))
152
153def encode.levels(levels: List<&2, List<&2, String>>) -> Bytes.Bytes:
154  match levels:
155    case Nil{}:
156      Bytes.new(0)
157    case Con{+names, rest}:
158      Bytes.concat([u32(U32.from_nat(List.length(&2, String, names))), encode.names(names), encode.levels(rest)])
159
160def encode.body(+manifest: Manifest) -> Bytes.Bytes:
161  match manifest:
162    case M{levels}:
163      Bytes.concat([magic(), u32(3), u32(U32.from_nat(List.length(&2, List<&2, String>, levels))), encode.levels(levels)])
164
165def encode.digest.checked(pair: Bytes.Bytes & Bytes.Bytes) -> Result<&1, &1, Error, Bytes.Bytes>:
166  match pair:
167    case (packed, size_packed):
168      Bool.pick(Result<&1, &1, Error, Bytes.Bytes>,
169        U32.is_le(bytes.length(Bytes.length(size_packed)), StorageBytes.MAX_MANIFEST_BYTES()),
170        Done{packed}, Fail{TooLarge{}})
171
172def encode.body.digest(pair: Bytes.Bytes & Bytes.Bytes) -> Result<&1, &1, Error, Bytes.Bytes>:
173      match pair:
174        case (body, hash_body):
175          encode.digest.checked(bytes.clone.split(Bytes.concat([body, SHA.sha256_packed_bytes(hash_body)])))
176
177def encode.body.checked(manifest: Manifest) -> Result<&1, &1, Error, Bytes.Bytes>:
178      body_pair = bytes.clone.split(encode.body(manifest))
179      encode.body.digest(body_pair)
180
181def encode.checked(manifest: Manifest, valid: Bool) -> Result<&1, &1, Error, Bytes.Bytes>:
182  match valid:
183    case False{}:
184      Fail{InvalidName{}}
185    case True{}:
186      encode.body.checked(manifest)
187
188def manifest.valid(manifest: Manifest) -> Bool:
189  match manifest:
190    case M{levels}:
191      levels.valid(levels)
192
193# Handle serialize in the binary manifest codec.
194def serialize(+manifest: Manifest) -> Result<&1, &1, Error, Bytes.Bytes>:
195  encode.checked(manifest, manifest.valid(manifest))
196
197def token.from.result(result: Result<&1, &1, Error, Bytes.Bytes>) -> String:
198  match result:
199    case Done{bytes}:
200      Bytes.to_hex(bytes)
201    case Fail{_}:
202      ""
203
204# Handle token in the binary manifest codec.
205def token(manifest: Manifest) -> String:
206  token.from.result(serialize(manifest))
207
208
209def cursor.u32(cursor: Bytes.Cursor) -> Bytes.Cursor & Maybe<&2, U32>:
210  Bytes.Cursor.u32be(cursor)
211
212def cursor.bytes(cursor: Bytes.Cursor, len: U32) -> Bytes.Cursor & Maybe<&1, Bytes.CursorLimit>:
213  Bytes.Cursor.region(cursor, len)
214
215def read.name.text(
216  cursor: Bytes.Cursor,
217  limit: Bytes.CursorLimit,
218  name: String,
219  valid: Bool
220) -> Bytes.Cursor & Maybe<&2, String>:
221  match valid:
222    case False{}:
223      (Bytes.Cursor.leave(cursor, limit), None{})
224    case True{}:
225      (Bytes.Cursor.leave(cursor, limit), Some{name})
226
227def read.name.decoded(
228  cursor: Bytes.Cursor,
229  limit: Bytes.CursorLimit,
230  decoded: Result<&1, &1, U32 & String, String>
231) -> Bytes.Cursor & Maybe<&2, String>:
232  match decoded:
233    case Fail{_}:
234      (Bytes.Cursor.leave(cursor, limit), None{})
235    case Done{+name}:
236      read.name.text(cursor, limit, name, name.text.valid(name))
237
238def read.name.checked(
239  cursor: Bytes.Cursor,
240  limit: Bytes.CursorLimit,
241  bytes: Bytes.Bytes
242) -> Bytes.Cursor & Maybe<&2, String>:
243  read.name.decoded(cursor, limit, StorageBytes.to_string_strict(bytes))
244
245def read.name.buffer.copies(
246  limit: Bytes.CursorLimit,
247  len: U32,
248  +offset: U32,
249  start: U32,
250  end: U32,
251  copies: Bytes.Bytes & Bytes.Bytes
252) -> Bytes.Cursor & Maybe<&2, String>:
253  match copies:
254    case (cursor_bytes, slice_bytes):
255      read.name.checked(Bytes.Cursor{cursor_bytes, offset, start, end}, limit,
256        bytes.slice.second(Bytes.slice(slice_bytes, offset, len)))
257
258def read.name.buffer(cursor: Bytes.Cursor, limit: Bytes.CursorLimit, len: U32) -> Bytes.Cursor & Maybe<&2, String>:
259  match cursor:
260    case Bytes.Cursor{source, +offset, +start, +end}:
261      read.name.buffer.copies(limit, len, offset, start, end, bytes.clone.split(source))
262
263def read.name.region.result(
264  region: Bytes.Cursor & Maybe<&1, Bytes.CursorLimit>,
265  len: U32
266) -> Bytes.Cursor & Maybe<&2, String>:
267  match region:
268    case (next, None{}):
269      (next, None{})
270    case (next, Some{limit}):
271      read.name.buffer(next, limit, len)
272
273def read.name.region(cursor: Bytes.Cursor, +len: U32) -> Bytes.Cursor & Maybe<&2, String>:
274  read.name.region.result(cursor.bytes(cursor, len), len)
275
276def read.name(pair: Bytes.Cursor & Maybe<&2, U32>) -> Bytes.Cursor & Maybe<&2, String>:
277  match pair:
278    case (cursor, None{}):
279      (cursor, None{})
280    case (cursor, Some{len}):
281      read.name.region(cursor, len)
282
283def parse.step.reject.name(value: Bytes.Cursor & Maybe<&2, String>) -> ParseTransition:
284  match value:
285    case (cursor, _):
286      Reject{cursor}
287
288def parse.step.reject(input: ParseInput) -> ParseTransition:
289  match input:
290    case NoInput{cursor}:
291      Reject{cursor}
292    case NameInput{value}:
293      parse.step.reject.name(value)
294
295def parse.step.count.value(
296  levels_left: Nat,
297  levels_acc: List<&2, List<&2, String>>,
298  value: Bytes.Cursor & Maybe<&2, U32>
299) -> ParseTransition:
300  match value:
301    case (cursor, None{}):
302      Reject{cursor}
303    case (cursor, Some{count}):
304      Continue{ReadNameLength{levels_left, levels_acc, U32.to_nat(count), Nil{}}, NoInput{cursor}}
305
306def parse.step.count(levels_left: Nat, levels_acc: List<&2, List<&2, String>>, input: ParseInput) -> ParseTransition:
307  match input:
308    case NoInput{cursor}:
309      parse.step.count.value(levels_left, levels_acc, cursor.u32(cursor))
310    case NameInput{_}:
311      parse.step.reject(input)
312
313def parse.step.length.named(
314  levels_left: Nat,
315  levels_acc: List<&2, List<&2, String>>,
316  names_left: Nat,
317  names_acc: List<&2, String>,
318  value: Bytes.Cursor & Maybe<&2, String>
319) -> ParseTransition:
320  Continue{ReadNameBody{levels_left, levels_acc, names_left, names_acc}, NameInput{value}}
321
322def parse.step.length.value(
323  levels_left: Nat,
324  levels_acc: List<&2, List<&2, String>>,
325  names_left: Nat,
326  names_acc: List<&2, String>,
327  value: Bytes.Cursor & Maybe<&2, U32>
328) -> ParseTransition:
329  match value:
330    case (cursor, None{}):
331      Reject{cursor}
332    case (cursor, Some{len}):
333      parse.step.length.named(levels_left, levels_acc, names_left, names_acc, read.name((cursor, Some{len})))
334
335def parse.step.length.input(
336  levels_left: Nat,
337  levels_acc: List<&2, List<&2, String>>,
338  names_left: Nat,
339  names_acc: List<&2, String>,
340  input: ParseInput
341) -> ParseTransition:
342  match input:
343    case NoInput{cursor}:
344      parse.step.length.value(levels_left, levels_acc, names_left, names_acc, cursor.u32(cursor))
345    case NameInput{_}:
346      parse.step.reject(input)
347
348def parse.step.level.remaining(
349  levels_left: Nat,
350  levels_acc: List<&2, List<&2, String>>,
351  names: List<&2, String>,
352  cursor: Bytes.Cursor
353) -> ParseTransition:
354  match levels_left:
355    case 0n:
356      Reject{cursor}
357    case 1n+rest:
358      match rest:
359        case 0n:
360          Finish{cursor, List.reverse(&2, List<&2, String>, Con{names, levels_acc})}
361        case 1n+more:
362          Continue{ReadNamesCount{1n+more, Con{names, levels_acc}}, NoInput{cursor}}
363
364def parse.step.level(
365  levels_left: Nat,
366  levels_acc: List<&2, List<&2, String>>,
367  names_acc: List<&2, String>,
368  input: ParseInput
369) -> ParseTransition:
370  match input:
371    case NoInput{cursor}:
372      parse.step.level.remaining(levels_left, levels_acc, List.reverse(&2, String, names_acc), cursor)
373    case NameInput{_}:
374      parse.step.reject(input)
375
376def parse.step.name.value(
377  levels_left: Nat,
378  levels_acc: List<&2, List<&2, String>>,
379  names_left: Nat,
380  names_acc: List<&2, String>,
381  value: Bytes.Cursor & Maybe<&2, String>
382) -> ParseTransition:
383  match value:
384    case (cursor, None{}):
385      Reject{cursor}
386    case (cursor, Some{name}):
387      Continue{ReadNameLength{levels_left, levels_acc, names_left, Con{name, names_acc}}, NoInput{cursor}}
388
389def parse.step.name(
390  levels_left: Nat,
391  levels_acc: List<&2, List<&2, String>>,
392  names_left: Nat,
393  names_acc: List<&2, String>,
394  input: ParseInput
395) -> ParseTransition:
396  match input:
397    case NameInput{value}:
398      parse.step.name.value(levels_left, levels_acc, names_left, names_acc, value)
399    case NoInput{_}:
400      parse.step.reject(input)
401
402def parse.step.state(state: ParseState, input: ParseInput) -> ParseTransition:
403  match state:
404    case ReadNamesCount{levels_left, levels_acc}:
405      parse.step.count(levels_left, levels_acc, input)
406    case ReadNameLength{levels_left, levels_acc, names_left, names_acc}:
407      match names_left:
408        case 0n:
409          parse.step.level(levels_left, levels_acc, names_acc, input)
410        case 1n+rest:
411          parse.step.length.input(levels_left, levels_acc, rest, names_acc, input)
412    case ReadNameBody{levels_left, levels_acc, names_left, names_acc}:
413      parse.step.name(levels_left, levels_acc, names_left, names_acc, input)
414
415def parse.loop.exhausted.name(value: Bytes.Cursor & Maybe<&2, String>) -> Bytes.Cursor & Maybe<&2, Manifest>:
416  match value:
417    case (cursor, _):
418      (cursor, None{})
419
420def parse.loop.exhausted(transition: ParseTransition) -> Bytes.Cursor & Maybe<&2, Manifest>:
421  match transition:
422    case Continue{_, NoInput{cursor}}:
423      (cursor, None{})
424    case Continue{_, NameInput{value}}:
425      parse.loop.exhausted.name(value)
426    case Reject{cursor}:
427      (cursor, None{})
428    case Finish{cursor, _}:
429      (cursor, None{})
430
431def parse.loop(fuel: Nat, transition: ParseTransition) -> Bytes.Cursor & Maybe<&2, Manifest>:
432  match fuel:
433    case 0n:
434      parse.loop.exhausted(transition)
435    case 1n+rest:
436      match transition:
437        case Reject{cursor}:
438          (cursor, None{})
439        case Finish{cursor, levels}:
440          (cursor, Some{M{levels}})
441        case Continue{state, input}:
442          parse.loop(rest, parse.step.state(state, input))
443
444def bytes.eq.result(comparison: Bytes.Bytes & Bytes.Bytes & Bool) -> Bool:
445  match comparison:
446    case (_, _, equal):
447      equal
448
449def checksum.valid(bytes: Bytes.Bytes, body_len: U32, digest: Bytes.Bytes) -> Bool:
450  bytes.eq.result(Bytes.eq(SHA.sha256_packed_bytes(bytes.slice.second(Bytes.slice(bytes, 0, body_len))), digest))
451
452def parse.body.digest.verified(
453  body_len: U32,
454  hash_source: Bytes.Bytes,
455  levels: List<&2, List<&2, String>>,
456  digest: Bytes.Bytes
457) -> Maybe<&2, Manifest>:
458  Bool.pick(Maybe<&2, Manifest>, checksum.valid(hash_source, body_len, digest), Some{M{levels}}, None{})
459
460def parse.body.digest.footer(
461  +body_len: U32,
462  hash_source: Bytes.Bytes,
463  levels: List<&2, List<&2, String>>,
464  copies: Bytes.Bytes & Bytes.Bytes
465) -> Maybe<&2, Manifest>:
466  match copies:
467    case (_, digest_source):
468      parse.body.digest.verified(body_len, hash_source, levels, bytes.slice.second(Bytes.slice(digest_source, body_len, 32)))
469
470def parse.body.digest.checked(
471  body_len: U32,
472  hash_source: Bytes.Bytes,
473  footer_source: Bytes.Bytes,
474  levels: List<&2, List<&2, String>>,
475  within_size: Bool
476) -> Maybe<&2, Manifest>:
477  match within_size:
478    case False{}:
479      None{}
480    case True{}:
481      parse.body.digest.footer(body_len, hash_source, levels, bytes.clone.split(footer_source))
482
483def parse.body.digest.size(
484  +body_len: U32,
485  hash_source: Bytes.Bytes,
486  size_pair: Bytes.Bytes & U32,
487  levels: List<&2, List<&2, String>>
488) -> Maybe<&2, Manifest>:
489  match size_pair:
490    case (footer_source, +total):
491      parse.body.digest.checked(body_len, hash_source, footer_source, levels, U32.is_eq(total, (body_len + 32 : U32)))
492
493def parse.body.digest.sources(
494  body_len: U32,
495  levels: List<&2, List<&2, String>>,
496  sources: Bytes.Bytes & Bytes.Bytes
497) -> Maybe<&2, Manifest>:
498  match sources:
499    case (hash_source, footer_source):
500      parse.body.digest.size(body_len, hash_source, Bytes.length(footer_source), levels)
501
502def parse.body.position(
503  cursor: Bytes.Cursor,
504  source: Bytes.Bytes,
505  levels: List<&2, List<&2, String>>
506) -> Maybe<&2, Manifest>:
507  match cursor:
508    case Bytes.Cursor{_, +body_len, _, _}:
509      parse.body.digest.sources(body_len, levels, bytes.clone.split(source))
510
511def parse.body.levels.manifest(cursor: Bytes.Cursor, source: Bytes.Bytes, manifest: Manifest) -> Maybe<&2, Manifest>:
512  match manifest:
513    case M{levels}:
514      parse.body.position(cursor, source, levels)
515
516def parse.body.levels(source: Bytes.Bytes, result: Bytes.Cursor & Maybe<&2, Manifest>) -> Maybe<&2, Manifest>:
517  match result:
518    case (_, None{}):
519      None{}
520    case (body_end, Some{manifest}):
521      parse.body.levels.manifest(body_end, source, manifest)
522
523def parse.body.start(count: Nat, cursor: Bytes.Cursor, source: Bytes.Bytes) -> Maybe<&2, Manifest>:
524  match count:
525    case 0n:
526      parse.body.levels(source, parse.loop(Nat.add(Nat.mul(3n, U32.to_nat(StorageBytes.MAX_MANIFEST_BYTES())), 16n), Finish{cursor, Nil{}}))
527    case 1n+rest:
528      parse.body.levels(source, parse.loop(Nat.add(Nat.mul(3n, U32.to_nat(StorageBytes.MAX_MANIFEST_BYTES())), 16n), Continue{ReadNamesCount{1n+rest, Nil{}}, NoInput{cursor}}))
529
530def parse.body(pair: Bytes.Cursor & Maybe<&2, U32>, source: Bytes.Bytes) -> Maybe<&2, Manifest>:
531  match pair:
532    case (_, None{}):
533      None{}
534    case (cursor, Some{count}):
535      parse.body.start(U32.to_nat(count), cursor, source)
536
537def parse.version(cursor: Bytes.Cursor, source: Bytes.Bytes, valid: Bool) -> Maybe<&2, Manifest>:
538  match valid:
539    case False{}:
540      None{}
541    case True{}:
542      parse.body(cursor.u32(cursor), source)
543
544def parse.magic(pair: Bytes.Cursor & Maybe<&2, U32>, source: Bytes.Bytes) -> Maybe<&2, Manifest>:
545  match pair:
546    case (_, None{}):
547      None{}
548    case (cursor, Some{version}):
549      parse.version(cursor, source, U32.is_eq(version, 3))
550
551def parse.input.second.valid(source: Bytes.Bytes, cursor: Bytes.Cursor, valid: Bool) -> Maybe<&2, Manifest>:
552  match valid:
553    case False{}:
554      None{}
555    case True{}:
556      parse.magic(cursor.u32(cursor), source)
557
558def parse.input.second(source: Bytes.Bytes, pair: Bytes.Cursor & Maybe<&2, U32>) -> Maybe<&2, Manifest>:
559  match pair:
560    case (_, None{}):
561      None{}
562    case (cursor, Some{second}):
563      parse.input.second.valid(source, cursor, U32.is_eq(second, 1295207680))
564
565def parse.input.first.valid(source: Bytes.Bytes, cursor: Bytes.Cursor, valid: Bool) -> Maybe<&2, Manifest>:
566  match valid:
567    case False{}:
568      None{}
569    case True{}:
570      parse.input.second(source, cursor.u32(cursor))
571
572def parse.input.first(source: Bytes.Bytes, pair: Bytes.Cursor & Maybe<&2, U32>) -> Maybe<&2, Manifest>:
573  match pair:
574    case (_, None{}):
575      None{}
576    case (cursor, Some{first}):
577      parse.input.first.valid(source, cursor, U32.is_eq(first, 1297697875))
578
579def parse.input.start(sources: Bytes.Bytes & Bytes.Bytes) -> Maybe<&2, Manifest>:
580  match sources:
581    case (source, cursor_source):
582      parse.input.first(source, Bytes.Cursor.u32be(Bytes.Cursor.new(cursor_source)))
583
584def parse.input.with_magic(source: Bytes.Bytes) -> Maybe<&2, Manifest>:
585  parse.input.start(bytes.clone.split(source))
586
587def parse.bounded(source: Bytes.Bytes, within_limit: Bool) -> Maybe<&2, Manifest>:
588  match within_limit:
589    case False{}:
590      None{}
591    case True{}:
592      parse.input.with_magic(source)
593
594def parse.size(size_pair: Bytes.Bytes & U32) -> Maybe<&2, Manifest>:
595  match size_pair:
596    case (source, len):
597      parse.bounded(source, U32.is_le(len, StorageBytes.MAX_MANIFEST_BYTES()))
598
599# Handle parse in the binary manifest codec.
600def parse(source: Bytes.Bytes) -> Maybe<&2, Manifest>:
601  parse.size(Bytes.length(source))
602
603# Check whether decided holds for the binary manifest codec.
604def is_decided(_result: Maybe<&2, Manifest>) -> Bool:
605  True{}