[{"name":"Bytes.Decoder","comment":" Fast bytes decoder with error reporting and `oneOf` branching.\n\n\n# Architecture\n\nEach `Decoder` carries two execution strategies:\n\n1.  **Fast path** — a raw `elm/bytes` `Bytes.Decode.Decoder` composed via\n    `Decode.map2`, `Decode.andThen`, `Decode.loop`, etc. When present, `decode`\n    executes a single `Decode.decode` call with zero per-step overhead. This\n    matches the performance of hand-written `elm/bytes` decoders.\n\n2.  **Slow path** — a state-passing function that tracks byte offsets, reports\n    structured errors, and supports backtracking in `oneOf`. This path is only\n    executed when the fast path is unavailable or returns `Nothing` (i.e. an\n    error occurred).\n\nThe key insight is that most decoders succeed on well-formed input. By deferring\nerror tracking to a re-decode, the happy path pays no cost for error reporting.\n\n\n# Fast-path availability\n\nNot every combinator can be expressed as a raw `Bytes.Decode.Decoder`:\n\n  - **Always fast**: `succeed`, `map`, `map2`–`map5`, `keep`, `ignore`, `skip`,\n    `andThen`, `loop`, `repeat`, and all primitives.\n  - **Always slow**: `fail` (no decoder can produce a value), `oneOf`\n    (requires backtracking which `Bytes.Decode.Decoder` cannot do mid-stream).\n  - **Conditionally fast**: `andThen` and `loop` remain fast as long as the\n    callback returns a decoder with a fast path. If a callback branch returns\n    `fail`, that branch uses `Decode.fail` to signal the raw decoder, which causes\n    `Decode.decode` to return `Nothing` and triggers the slow re-decode.\n\nIn practice, `fail` branches inside `andThen` are error-handling code that only\nruns on malformed input — exactly when we want to re-decode with error tracking.\nBeware that if `oneOf` is used, it will turn the whole decoder into the slow path!\nSo avoid it as much as possible.\n\n\n# Running\n\n@docs Decoder, decode, Error\n\n\n# Static\n\n@docs succeed, fail, inContext\n\n\n# Primitives\n\n\n## Integers\n\n@docs unsignedInt8, unsignedInt16, unsignedInt32, signedInt8, signedInt16, signedInt32\n\n\n## Floats\n\n@docs float16, float32, float64\n\n\n## Strings\n\n@docs string\n\n\n## Raw Bytes\n\n@docs bytes, skipBytes\n\n\n# Mapping\n\n@docs map, map2, map3, map4, map5\n\n\n# Pipeline\n\n@docs keep, ignore, skip\n\n\n# Chaining\n\n@docs andThen, oneOf, repeat, Step, loop\n\n\n# Random access\n\n@docs Position, position, startOfInput, randomAccess\n\n\n# Advanced\n\n@docs fromDecoderUnsafe\n\n","unions":[{"name":"Decoder","comment":" A decoder that reads binary data and produces either a value or an error.\n\nInternally, it carries an optional raw `Bytes.Decode.Decoder` (fast path) and a\nstate-passing function (slow path for error reporting).\n\n","args":["context","error","value"],"cases":[]},{"name":"Error","comment":" Describes errors that arise while decoding.\n\nCustom errors happen through [`fail`](#fail), context tracking happens through\n[`inContext`](#inContext).\n\n","args":["context","error"],"cases":[["InContext",["{ label : context, start : Basics.Int }","Bytes.Decoder.Error context error"]],["OutOfBounds",["{ at : Basics.Int, bytes : Basics.Int }"]],["Custom",["{ at : Basics.Int }","error"]],["BadOneOf",["{ at : Basics.Int }","List.List (Bytes.Decoder.Error context error)"]]]},{"name":"Position","comment":" An opaque position in the input, obtained via [`position`](#position).\n","args":[],"cases":[]},{"name":"Step","comment":" Represent the next step of a loop: either continue with updated state,\nor finish with a final value.\n","args":["state","a"],"cases":[["Loop",["state"]],["Done",["a"]]]}],"aliases":[],"values":[{"name":"andThen","comment":" Decode one thing, then decode another thing based on the result.\n\nThe fast path uses `Decode.andThen`. If the callback returns a decoder without\na fast path (e.g. via `fail`), the fast decoder signals failure via\n`Decode.fail`, causing `decode` to fall back to the slow path.\n\n","type":"(a -> Bytes.Decoder.Decoder context error b) -> Bytes.Decoder.Decoder context error a -> Bytes.Decoder.Decoder context error b"},{"name":"bytes","comment":" Decode exactly `n` bytes.\n","type":"Basics.Int -> Bytes.Decoder.Decoder context error Bytes.Bytes"},{"name":"decode","comment":" Run the given decoder on the provided bytes.\n\nFirst tries the fast path (a single `Decode.decode` call). If the fast path is\nunavailable or fails, re-decodes with the slow path to produce a detailed error.\n\n","type":"Bytes.Decoder.Decoder context error value -> Bytes.Bytes -> Result.Result (Bytes.Decoder.Error context error) value"},{"name":"fail","comment":" Always fail with the given error.\n\nThis decoder has no fast path — using it (even in a branch of `andThen`) will\ncause `decode` to fall back to the slow path for error reporting.\n\n","type":"error -> Bytes.Decoder.Decoder context error value"},{"name":"float16","comment":" Decode two bytes as a 16-bit float.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Float"},{"name":"float32","comment":" Decode four bytes as a 32-bit float.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Float"},{"name":"float64","comment":" Decode eight bytes as a 64-bit float.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Float"},{"name":"fromDecoderUnsafe","comment":" Wrap a raw `Bytes.Decode.Decoder` into a `Decoder` with error reporting.\n\nThis is an escape hatch for advanced users who already have a working\n`Bytes.Decode.Decoder` and want to use it within this library's decoder\npipeline. You must supply:\n\n  - `error` — the error to report if the inner decoder fails\n  - `byteLength` — the **exact** number of bytes the inner decoder consumes on\n    success\n  - the raw `Bytes.Decode.Decoder` to wrap\n\n**The recommended approach** is to rewrite your decoder using the functions\nprovided by this module — they cover all the functionality of the original\n`Bytes.Decode` module while providing error reporting and `oneOf` branching.\n\n**This function is unsafe** because the caller is responsible for providing the\ncorrect byte width. If the byte length is wrong, the offset tracking in the slow\npath will be incorrect, leading to corrupt subsequent decoding. This also means\nit **must not** be used for variable-length decoders (e.g. decoders that read a\nlength prefix and then consume that many bytes) — only for fixed-width decoders\nwhere the byte count is known statically.\n\n","type":"error -> Basics.Int -> Bytes.Decode.Decoder value -> Bytes.Decoder.Decoder context error value"},{"name":"ignore","comment":" Run a decoder but discard its result, keeping the previous value.\n\nThe ignored decoder must still succeed for the pipeline to succeed.\n\n","type":"Bytes.Decoder.Decoder context error ignore -> Bytes.Decoder.Decoder context error keep -> Bytes.Decoder.Decoder context error keep"},{"name":"inContext","comment":" Add context to errors that may occur during decoding.\n\nThe fast path is preserved (context only matters on the error path).\n\n","type":"context -> Bytes.Decoder.Decoder context error value -> Bytes.Decoder.Decoder context error value"},{"name":"keep","comment":" Decode a value and apply it to the function held by the previous decoder.\n\n    import Bytes.Decoder as BD\n\n    BD.succeed Record\n        |> BD.keep BD.unsignedInt8\n        |> BD.keep BD.unsignedInt8\n        |> BD.keep BD.unsignedInt8\n\n","type":"Bytes.Decoder.Decoder context error a -> Bytes.Decoder.Decoder context error (a -> b) -> Bytes.Decoder.Decoder context error b"},{"name":"loop","comment":" Decode in a loop. Each iteration produces either `Loop` (continue with new\nstate) or `Done` (finish with a value).\n\nThe fast path uses `Decode.loop` (a tight `while` loop in the JS kernel).\nIf any iteration's callback returns a decoder without a fast path, the fast\ndecoder signals failure via `Decode.fail` and `decode` falls back to the slow\npath.\n\n","type":"(state -> Bytes.Decoder.Decoder context error (Bytes.Decoder.Step state a)) -> state -> Bytes.Decoder.Decoder context error a"},{"name":"map","comment":" Transform the value a decoder produces.\n","type":"(a -> b) -> Bytes.Decoder.Decoder context error a -> Bytes.Decoder.Decoder context error b"},{"name":"map2","comment":" Combine what 2 decoders produce.\n","type":"(x -> y -> z) -> Bytes.Decoder.Decoder context error x -> Bytes.Decoder.Decoder context error y -> Bytes.Decoder.Decoder context error z"},{"name":"map3","comment":" Combine what 3 decoders produce.\n","type":"(w -> x -> y -> z) -> Bytes.Decoder.Decoder context error w -> Bytes.Decoder.Decoder context error x -> Bytes.Decoder.Decoder context error y -> Bytes.Decoder.Decoder context error z"},{"name":"map4","comment":" Combine what 4 decoders produce.\n","type":"(v -> w -> x -> y -> z) -> Bytes.Decoder.Decoder context error v -> Bytes.Decoder.Decoder context error w -> Bytes.Decoder.Decoder context error x -> Bytes.Decoder.Decoder context error y -> Bytes.Decoder.Decoder context error z"},{"name":"map5","comment":" Combine what 5 decoders produce.\n","type":"(u -> v -> w -> x -> y -> z) -> Bytes.Decoder.Decoder context error u -> Bytes.Decoder.Decoder context error v -> Bytes.Decoder.Decoder context error w -> Bytes.Decoder.Decoder context error x -> Bytes.Decoder.Decoder context error y -> Bytes.Decoder.Decoder context error z"},{"name":"oneOf","comment":" Try each decoder in order, returning the first success.\n\nThis decoder has no fast path — it always uses the slow path with backtracking.\nBeware that the slow path is contaminating, meaning all decoders in the chain also turn to the slow path.\nFor tag-based dispatch, prefer `andThen` which preserves the fast path.\n\nCollects all errors on failure for diagnostic purposes.\n\n**Caution:** `oneOf` backtracks by byte offset, not by meaning. If two branches\nconsume the same number of bytes but interpret them differently (e.g.\n`unsignedInt32` vs `float32`), the first branch that successfully reads those\nbytes wins — even if the value makes no sense for your domain. In general,\nraw byte sequences are untagged, so `oneOf` cannot distinguish between\nalternatives that happen to have the same byte layout. Prefer `andThen` with\nan explicit tag byte whenever possible.\n\n","type":"List.List (Bytes.Decoder.Decoder context error value) -> Bytes.Decoder.Decoder context error value"},{"name":"position","comment":" Produce the current byte offset in the input.\n\nThis decoder has no fast path — using it will cause `decode` to fall back to\nthe slow path.\n\n    import Bytes.Decoder as BD\n\n    BD.decode BD.position (fromList [ 1, 2, 3 ])\n    --> Ok BD.startOfInput\n\n    BD.decode\n        (BD.unsignedInt8\n            |> BD.andThen (\\_ -> BD.position)\n        )\n        (fromList [ 1, 2, 3 ])\n        |> Result.map (\\\\p -> p == BD.startOfInput)\n    --> Ok False\n\n","type":"Bytes.Decoder.Decoder context error Bytes.Decoder.Position"},{"name":"randomAccess","comment":" Read data at an arbitrary offset, then resume where you left off.\n\nThis decoder has no fast path.\n\nAs an example, consider data laid out as:\n\n  - A byte giving the length of a string\n  - A byte giving the absolute offset to the string\n  - Another byte we also need\n\n<!-- -->\n\n    import Bytes exposing (Bytes)\n    import Bytes.Decoder as BD exposing (Decoder)\n    import Bytes.Encode as E\n\n    input : Bytes\n    input =\n        [ E.unsignedInt8 5\n        , E.unsignedInt8 15\n        , E.unsignedInt8 6\n        , E.string (String.repeat 12 \"\\u{0000}\")\n        , E.string \"hello\"\n        ]\n            |> E.sequence\n            |> E.encode\n\n    stringAtOffset : Decoder c e String\n    stringAtOffset =\n        BD.map2 Tuple.pair BD.unsignedInt8 BD.unsignedInt8\n            |> BD.andThen\n                (\\( len, offset ) ->\n                    BD.randomAccess\n                        { offset = offset, relativeTo = BD.startOfInput }\n                        (BD.string len)\n                )\n\n    BD.decode stringAtOffset input\n    --> Ok \"hello\"\n\nParsing continues at the sequential position after `randomAccess` returns:\n\n    final : Decoder c e { string : String, number : Int }\n    final =\n        BD.succeed (\\s n -> { string = s, number = n })\n            |> BD.keep stringAtOffset\n            |> BD.keep BD.unsignedInt8\n\n    BD.decode final input\n    --> Ok { string = \"hello\", number = 6 }\n\n","type":"{ offset : Basics.Int, relativeTo : Bytes.Decoder.Position } -> Bytes.Decoder.Decoder context error value -> Bytes.Decoder.Decoder context error value"},{"name":"repeat","comment":" Decode exactly `count` copies of the same decoder into a list.\n\nIf the inner decoder has a fast path, `repeat` preserves it by composing\na single `Decode.loop` decoder.\n\n","type":"Bytes.Decoder.Decoder context error value -> Basics.Int -> Bytes.Decoder.Decoder context error (List.List value)"},{"name":"signedInt16","comment":" Decode two bytes as a signed integer from -32768 to 32767.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Int"},{"name":"signedInt32","comment":" Decode four bytes as a signed integer from -2147483648 to 2147483647.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Int"},{"name":"signedInt8","comment":" Decode one byte as a signed integer from -128 to 127.\n","type":"Bytes.Decoder.Decoder context error Basics.Int"},{"name":"skip","comment":" Skip `n` bytes, then continue with the given decoder.\n","type":"Basics.Int -> Bytes.Decoder.Decoder context error value -> Bytes.Decoder.Decoder context error value"},{"name":"skipBytes","comment":" Skip exactly `count` bytes, producing `()`.\n\nUnlike [`skip`](#skip) which is a pipeline combinator that takes a decoder\nto continue with, `skipBytes` is a standalone decoder.\n\n","type":"Basics.Int -> Bytes.Decoder.Decoder context error ()"},{"name":"startOfInput","comment":" The position at the very start of the input (offset 0).\n\nUseful as the `relativeTo` argument in [`randomAccess`](#randomAccess).\n\n","type":"Bytes.Decoder.Position"},{"name":"string","comment":" Decode exactly `n` bytes as a UTF-8 string.\n","type":"Basics.Int -> Bytes.Decoder.Decoder context error String.String"},{"name":"succeed","comment":" Always succeed with the given value, consuming no input.\n","type":"value -> Bytes.Decoder.Decoder context error value"},{"name":"unsignedInt16","comment":" Decode two bytes as an unsigned integer from 0 to 65535.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Int"},{"name":"unsignedInt32","comment":" Decode four bytes as an unsigned integer from 0 to 4294967295.\n","type":"Bytes.Endianness -> Bytes.Decoder.Decoder context error Basics.Int"},{"name":"unsignedInt8","comment":" Decode one byte as an unsigned integer from 0 to 255.\n","type":"Bytes.Decoder.Decoder context error Basics.Int"}],"binops":[]}]