1 import Base 2 import ./StorageBytes.bend as StorageBytes 3 import bend-kit-bytes@0.3.2.0/bytes.bend as Bytes 4 import ./hub_sha/sha256.bend as SHA 5 6 # Represent Manifest data used by the binary manifest codec. 7 type Manifest is Data: 8 M{levels: List<&2, List<&2, String>>} 9 10 # Represent Error data used by the binary manifest codec. 11 type Error is Data: 12 TooLarge{} 13 InvalidName{} 14 15 # Represent ParseState data used by the binary manifest codec. 16 type 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. 22 type 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. 27 type 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 32 def 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. 40 def magic() -> Bytes.Bytes: 41 magic.result(Bytes.from_hex("4d594c534d334d00")) 42 43 # Handle u32 in the binary manifest codec. 44 def u32(+value: U32) -> Bytes.Bytes: 45 Bytes.set.u32be(Bytes.new(4), 0, value) 46 47 def bytes.clone.pair(+len: U32, copied: Array & Array) -> Bytes.Bytes & Bytes.Bytes: 48 match copied: 49 case (left, right): 50 (Bytes.Bytes{len, left}, Bytes.Bytes{len, right}) 51 52 def 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 57 def bytes.clone.first(pair: Bytes.Bytes & Bytes.Bytes) -> Bytes.Bytes: 58 match pair: 59 case (left, _): 60 left 61 62 def bytes.length(pair: Bytes.Bytes & U32) -> U32: 63 match pair: 64 case (_, len): 65 len 66 67 def bytes.slice.second(pair: Bytes.Bytes & Bytes.Bytes) -> Bytes.Bytes: 68 match pair: 69 case (_, second): 70 second 71 72 def encode.name.copies(+len: U32, tail: Bytes.Bytes, copies: Array & Array) -> Bytes.Bytes: 73 match copies: 74 case (stored, _unused): 75 Bytes.concat([u32(len), Bytes.Bytes{len, stored}, tail]) 76 77 def 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 82 def 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 87 def 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 94 def 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 101 def 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 108 def 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 115 def 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 122 def 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 131 def names.valid(names: List<&2, String>) -> Bool: 132 names.valid.step(names, True{}) 133 134 def 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 143 def levels.valid(levels: List<&2, List<&2, String>>) -> Bool: 144 levels.valid.step(levels, True{}) 145 146 def 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 153 def 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 160 def 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 165 def 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 172 def 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 177 def 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 181 def 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 188 def 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. 194 def serialize(+manifest: Manifest) -> Result<&1, &1, Error, Bytes.Bytes>: 195 encode.checked(manifest, manifest.valid(manifest)) 196 197 def 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. 205 def token(manifest: Manifest) -> String: 206 token.from.result(serialize(manifest)) 207 208 209 def cursor.u32(cursor: Bytes.Cursor) -> Bytes.Cursor & Maybe<&2, U32>: 210 Bytes.Cursor.u32be(cursor) 211 212 def cursor.bytes(cursor: Bytes.Cursor, len: U32) -> Bytes.Cursor & Maybe<&1, Bytes.CursorLimit>: 213 Bytes.Cursor.region(cursor, len) 214 215 def 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 227 def 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 238 def 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 245 def 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 258 def 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 263 def 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 273 def read.name.region(cursor: Bytes.Cursor, +len: U32) -> Bytes.Cursor & Maybe<&2, String>: 274 read.name.region.result(cursor.bytes(cursor, len), len) 275 276 def 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 283 def parse.step.reject.name(value: Bytes.Cursor & Maybe<&2, String>) -> ParseTransition: 284 match value: 285 case (cursor, _): 286 Reject{cursor} 287 288 def 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 295 def 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 306 def 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 313 def 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 322 def 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 335 def 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 348 def 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 364 def 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 376 def 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 389 def 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 402 def 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 415 def 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 420 def 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 431 def 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 444 def bytes.eq.result(comparison: Bytes.Bytes & Bytes.Bytes & Bool) -> Bool: 445 match comparison: 446 case (_, _, equal): 447 equal 448 449 def 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 452 def 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 460 def 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 470 def 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 483 def 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 493 def 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 502 def 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 511 def 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 516 def 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 523 def 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 530 def 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 537 def 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 544 def 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 551 def 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 558 def 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 565 def 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 572 def 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 579 def 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 584 def parse.input.with_magic(source: Bytes.Bytes) -> Maybe<&2, Manifest>: 585 parse.input.start(bytes.clone.split(source)) 586 587 def 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 594 def 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. 600 def parse(source: Bytes.Bytes) -> Maybe<&2, Manifest>: 601 parse.size(Bytes.length(source)) 602 603 # Check whether decided holds for the binary manifest codec. 604 def is_decided(_result: Maybe<&2, Manifest>) -> Bool: 605 True{}