-module(protozoa@decode). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/protozoa/decode.gleam"). -export([success/1, from_field_dict/1, fail/3, field/2, optional_field/2, field_with_default/3, repeated_field/2, varint_field/1, string_field/1, bytes_field/1, float_field/1, double_field/1, bool_field/1, int32_field/1, int64_field/1, uint32_field/1, uint64_field/1, fixed32_int_field/1, fixed64_int_field/1, sfixed32_field/1, sfixed64_field/1, int32/1, int32_with_default/2, int64_with_default/2, int64/1, uint32/1, uint32_with_default/2, uint64/1, uint64_with_default/2, string/1, string_with_default/2, bool/1, bool_with_default/2, bytes/1, float/1, double/1, fixed32/1, fixed64/1, sfixed32/1, sfixed64/1, repeated_int32/1, repeated_string/1, then/2, map/2, run/2, message_field/2, nested_message/2, optional_nested_message/2, decode_zigzag/1, sint32/1, sint64/1]). -export_type([decode_error/0, field/0, proto_value/0, decoder/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Protocol Buffer Decode Module \n" "\n" " This module provides a composable, type-safe API for decoding Protocol Buffer binary data\n" " into Gleam values. It follows the gleam/dynamic/decode pattern for familiar composability\n" " and error handling, making it easy to work with protobuf data in Gleam applications.\n" "\n" " ## Design Philosophy\n" "\n" " - **Composable decoders**: Small, focused decoder functions that can be combined\n" " - **Type safety**: Compile-time guarantees about decoded data structure\n" " - **Error handling**: Clear error messages for debugging decode failures\n" " - **Performance**: Efficient binary parsing with minimal allocations\n" " - **Gleam idioms**: Follows Result and Option patterns familiar to Gleam developers\n" "\n" " ## Capabilities\n" "\n" " - **All proto3 types**: Scalars (int32, string, bool), messages, enums, repeated fields\n" " - **Advanced features**: Oneofs, maps, optional fields, nested messages \n" " - **Wire format parsing**: Handles protobuf binary wire format correctly\n" " - **Field-level decoding**: Individual field decoders for fine-grained control\n" " - **Message-level decoding**: Complete message decoders with field validation\n" " - **Default values**: Proper proto3 default value handling\n" "\n" " ## Usage Pattern\n" "\n" " Generated code uses this module to create message-specific decoder functions:\n" " ```gleam\n" " pub fn decode_user(data: BitArray) -> Result(User, DecodeError) {\n" " decode.message(data, user_decoder())\n" " }\n" "\n" " fn user_decoder() -> decode.Decoder(User) {\n" " decode.into({\n" " use name <- decode.field(\"name\", decode.string_field(1))\n" " use age <- decode.field(\"age\", decode.int32_field(2)) \n" " User(name: name, age: age)\n" " })\n" " }\n" " ```\n" "\n" " ## Error Handling \n" "\n" " All decode functions return `Result(T, DecodeError)` with descriptive error messages\n" " for debugging binary format issues, missing required fields, or type mismatches.\n" ). -type decode_error() :: {decode_error, binary(), binary(), list(binary())} | {field_not_found, integer()}. -type field() :: {field, integer(), protozoa@wire:wire_type(), bitstring()}. -type proto_value() :: {proto_message, list(field())} | {proto_varint, integer()} | {proto_fixed32, bitstring()} | {proto_fixed64, bitstring()} | {proto_length_delimited, bitstring()}. -opaque decoder(NWT) :: {decoder, fun((gleam@dict:dict(integer(), list(field()))) -> {ok, NWT} | {error, list(decode_error())})}. -file("src/protozoa/decode.gleam", 119). ?DOC( " Create a decoder that always succeeds with a value.\n" " Useful for providing default values or building complex decoders.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " success(42) // Always returns Ok(42)\n" " ```\n" ). -spec success(NWZ) -> decoder(NWZ). success(Value) -> {decoder, fun(_) -> {ok, Value} end}. -file("src/protozoa/decode.gleam", 134). ?DOC( " Create a decoder from a function that takes a dict of fields.\n" " This is useful for creating custom decoders for complex types like oneofs.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " from_field_dict(fn(fields) {\n" " // Custom decoding logic using dict.get\n" " Ok(value)\n" " })\n" " ```\n" ). -spec from_field_dict( fun((gleam@dict:dict(integer(), list(field()))) -> {ok, NXE} | {error, list(decode_error())}) ) -> decoder(NXE). from_field_dict(F) -> {decoder, F}. -file("src/protozoa/decode.gleam", 148). ?DOC( " Create a decoder that always fails with an error message.\n" " Useful for handling unsupported fields or validation errors.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " fail(\"Unsupported field type\") // Always returns Error\n" " ```\n" ). -spec fail(binary(), binary(), list(binary())) -> decoder(any()). fail(Expected, Found, Path) -> {decoder, fun(_) -> {error, [{decode_error, Expected, Found, Path}]} end}. -file("src/protozoa/decode.gleam", 161). ?DOC( " Decode a required field with a specific decoder.\n" " Returns an error if the field is not present.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " field(1, varint_field) // Decodes field 1 as a varint\n" " field(2, string_field) // Decodes field 2 as a string\n" " ```\n" ). -spec field(integer(), fun((field()) -> {ok, NXM} | {error, decode_error()})) -> decoder(NXM). field(Number, Decoder) -> {decoder, fun(Fields) -> case gleam_stdlib:map_get(Fields, Number) of {ok, [Field | _]} -> _pipe = Decoder(Field), gleam@result:map_error(_pipe, fun(Err) -> [Err] end); {ok, []} -> {error, [{field_not_found, Number}]}; {error, _} -> {error, [{field_not_found, Number}]} end end}. -file("src/protozoa/decode.gleam", 185). ?DOC( " Decode an optional field.\n" " Returns Ok(Ok(value)) if the field is present and valid,\n" " Ok(Error(Nil)) if the field is missing or invalid.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " optional_field(1, varint_field) // Decodes optional field 1\n" " ```\n" ). -spec optional_field( integer(), fun((field()) -> {ok, NXQ} | {error, decode_error()}) ) -> decoder({ok, NXQ} | {error, nil}). optional_field(Number, Decoder) -> {decoder, fun(Fields) -> case gleam_stdlib:map_get(Fields, Number) of {ok, [Field | _]} -> case Decoder(Field) of {ok, Value} -> {ok, {ok, Value}}; {error, _} -> {ok, {error, nil}} end; {ok, []} -> {ok, {error, nil}}; {error, _} -> {ok, {error, nil}} end end}. -file("src/protozoa/decode.gleam", 211). ?DOC( " Decode a field with a default value.\n" " Returns the decoded value if present, otherwise returns the default.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " field_with_default(1, varint_field, 0) // Returns 0 if field 1 is missing\n" " ```\n" ). -spec field_with_default( integer(), fun((field()) -> {ok, NXW} | {error, decode_error()}), NXW ) -> decoder(NXW). field_with_default(Number, Decoder, Default) -> {decoder, fun(Fields) -> case gleam_stdlib:map_get(Fields, Number) of {ok, [Field | _]} -> case Decoder(Field) of {ok, Value} -> {ok, Value}; {error, _} -> {ok, Default} end; {ok, []} -> {ok, Default}; {error, _} -> {ok, Default} end end}. -file("src/protozoa/decode.gleam", 239). ?DOC( " Decode all fields with a given number (for repeated fields).\n" " Returns a list of all decoded values for the field number.\n" " Collects all errors encountered during decoding.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " repeated_field(1, varint_field) // Decodes all field 1 occurrences\n" " ```\n" ). -spec repeated_field( integer(), fun((field()) -> {ok, NYA} | {error, decode_error()}) ) -> decoder(list(NYA)). repeated_field(Number, Decoder) -> {decoder, fun(Fields) -> case gleam_stdlib:map_get(Fields, Number) of {ok, Field_list} -> Results = gleam@list:map(Field_list, Decoder), Errors = gleam@list:filter_map( Results, fun(Result) -> case Result of {error, Err} -> {ok, Err}; {ok, _} -> {error, nil} end end ), case Errors of [] -> Values = gleam@list:filter_map( Results, fun(Result@1) -> case Result@1 of {ok, Value} -> {ok, Value}; {error, _} -> {error, nil} end end ), {ok, Values}; _ -> {error, Errors} end; {error, _} -> {ok, []} end end}. -file("src/protozoa/decode.gleam", 278). ?DOC(false). -spec varint_field(field()) -> {ok, integer()} | {error, decode_error()}. varint_field(Field) -> case erlang:element(3, Field) of varint -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid varint data"/utf8>>, <<"invalid varint data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"varint wire type"/utf8>>, <<"non-varint wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 292). ?DOC(false). -spec string_field(field()) -> {ok, binary()} | {error, decode_error()}. string_field(Field) -> case erlang:element(3, Field) of length_delimited -> _pipe = gleam@bit_array:to_string(erlang:element(4, Field)), gleam@result:map_error( _pipe, fun(_) -> {decode_error, <<"valid UTF-8 string"/utf8>>, <<"invalid UTF-8 bytes"/utf8>>, []} end ); _ -> {error, {decode_error, <<"length-delimited wire type"/utf8>>, <<"non-length-delimited wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 313). ?DOC(false). -spec bytes_field(field()) -> {ok, bitstring()} | {error, decode_error()}. bytes_field(Field) -> case erlang:element(3, Field) of length_delimited -> {ok, erlang:element(4, Field)}; _ -> {error, {decode_error, <<"length-delimited wire type"/utf8>>, <<"non-length-delimited wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 329). ?DOC(false). -spec float_field(field()) -> {ok, float()} | {error, decode_error()}. float_field(Field) -> case erlang:element(3, Field) of fixed32 -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid 32-bit float data"/utf8>>, <<"invalid float data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"fixed32 wire type"/utf8>>, <<"non-fixed32 wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 346). ?DOC(false). -spec double_field(field()) -> {ok, float()} | {error, decode_error()}. double_field(Field) -> case erlang:element(3, Field) of fixed64 -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid 64-bit double data"/utf8>>, <<"invalid double data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"fixed64 wire type"/utf8>>, <<"non-fixed64 wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 363). ?DOC(false). -spec bool_field(field()) -> {ok, boolean()} | {error, decode_error()}. bool_field(Field) -> gleam@result:'try'(varint_field(Field), fun(Value) -> {ok, Value /= 0} end). -file("src/protozoa/decode.gleam", 370). ?DOC(false). -spec int32_field(field()) -> {ok, integer()} | {error, decode_error()}. int32_field(Field) -> varint_field(Field). -file("src/protozoa/decode.gleam", 376). ?DOC(false). -spec int64_field(field()) -> {ok, integer()} | {error, decode_error()}. int64_field(Field) -> varint_field(Field). -file("src/protozoa/decode.gleam", 382). ?DOC(false). -spec uint32_field(field()) -> {ok, integer()} | {error, decode_error()}. uint32_field(Field) -> varint_field(Field). -file("src/protozoa/decode.gleam", 388). ?DOC(false). -spec uint64_field(field()) -> {ok, integer()} | {error, decode_error()}. uint64_field(Field) -> varint_field(Field). -file("src/protozoa/decode.gleam", 394). ?DOC(false). -spec fixed32_int_field(field()) -> {ok, integer()} | {error, decode_error()}. fixed32_int_field(Field) -> case erlang:element(3, Field) of fixed32 -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid 32-bit integer data"/utf8>>, <<"invalid fixed32 data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"fixed32 wire type"/utf8>>, <<"non-fixed32 wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 411). ?DOC(false). -spec fixed64_int_field(field()) -> {ok, integer()} | {error, decode_error()}. fixed64_int_field(Field) -> case erlang:element(3, Field) of fixed64 -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid 64-bit integer data"/utf8>>, <<"invalid fixed64 data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"fixed64 wire type"/utf8>>, <<"non-fixed64 wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 428). ?DOC(false). -spec sfixed32_field(field()) -> {ok, integer()} | {error, decode_error()}. sfixed32_field(Field) -> case erlang:element(3, Field) of fixed32 -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid signed 32-bit integer data"/utf8>>, <<"invalid sfixed32 data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"fixed32 wire type"/utf8>>, <<"non-fixed32 wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 449). ?DOC(false). -spec sfixed64_field(field()) -> {ok, integer()} | {error, decode_error()}. sfixed64_field(Field) -> case erlang:element(3, Field) of fixed64 -> case erlang:element(4, Field) of <> -> {ok, Value}; _ -> {error, {decode_error, <<"valid signed 64-bit integer data"/utf8>>, <<"invalid sfixed64 data"/utf8>>, []}} end; _ -> {error, {decode_error, <<"fixed64 wire type"/utf8>>, <<"non-fixed64 wire type"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 492). ?DOC(" Decoder for int32 fields.\n"). -spec int32(integer()) -> decoder(integer()). int32(Number) -> field(Number, fun varint_field/1). -file("src/protozoa/decode.gleam", 497). ?DOC(" Decoder for int32 fields with a default value.\n"). -spec int32_with_default(integer(), integer()) -> decoder(integer()). int32_with_default(Number, Default) -> field_with_default(Number, fun varint_field/1, Default). -file("src/protozoa/decode.gleam", 501). -spec int64_with_default(integer(), integer()) -> decoder(integer()). int64_with_default(Number, Default) -> field_with_default(Number, fun varint_field/1, Default). -file("src/protozoa/decode.gleam", 506). ?DOC(" Decoder for int64 fields.\n"). -spec int64(integer()) -> decoder(integer()). int64(Number) -> field(Number, fun varint_field/1). -file("src/protozoa/decode.gleam", 511). ?DOC(" Decoder for uint32 fields.\n"). -spec uint32(integer()) -> decoder(integer()). uint32(Number) -> field(Number, fun varint_field/1). -file("src/protozoa/decode.gleam", 516). ?DOC(" Decoder for uint32 fields with a default value.\n"). -spec uint32_with_default(integer(), integer()) -> decoder(integer()). uint32_with_default(Number, Default) -> field_with_default(Number, fun varint_field/1, Default). -file("src/protozoa/decode.gleam", 521). ?DOC(" Decoder for uint64 fields.\n"). -spec uint64(integer()) -> decoder(integer()). uint64(Number) -> field(Number, fun varint_field/1). -file("src/protozoa/decode.gleam", 526). ?DOC(" Decoder for uint64 fields with a default value.\n"). -spec uint64_with_default(integer(), integer()) -> decoder(integer()). uint64_with_default(Number, Default) -> field_with_default(Number, fun varint_field/1, Default). -file("src/protozoa/decode.gleam", 531). ?DOC(" Decoder for string fields.\n"). -spec string(integer()) -> decoder(binary()). string(Number) -> field(Number, fun string_field/1). -file("src/protozoa/decode.gleam", 536). ?DOC(" Decoder for string fields with a default value.\n"). -spec string_with_default(integer(), binary()) -> decoder(binary()). string_with_default(Number, Default) -> field_with_default(Number, fun string_field/1, Default). -file("src/protozoa/decode.gleam", 541). ?DOC(" Decoder for boolean fields.\n"). -spec bool(integer()) -> decoder(boolean()). bool(Number) -> field(Number, fun bool_field/1). -file("src/protozoa/decode.gleam", 546). ?DOC(" Decoder for boolean fields with a default value.\n"). -spec bool_with_default(integer(), boolean()) -> decoder(boolean()). bool_with_default(Number, Default) -> field_with_default(Number, fun bool_field/1, Default). -file("src/protozoa/decode.gleam", 551). ?DOC(" Decoder for bytes fields.\n"). -spec bytes(integer()) -> decoder(bitstring()). bytes(Number) -> field(Number, fun bytes_field/1). -file("src/protozoa/decode.gleam", 556). ?DOC(" Decoder for float fields.\n"). -spec float(integer()) -> decoder(float()). float(Number) -> field(Number, fun float_field/1). -file("src/protozoa/decode.gleam", 561). ?DOC(" Decoder for double fields.\n"). -spec double(integer()) -> decoder(float()). double(Number) -> field(Number, fun double_field/1). -file("src/protozoa/decode.gleam", 566). ?DOC(" Decoder for fixed32 fields (unsigned 32-bit integers).\n"). -spec fixed32(integer()) -> decoder(integer()). fixed32(Number) -> field(Number, fun fixed32_int_field/1). -file("src/protozoa/decode.gleam", 571). ?DOC(" Decoder for fixed64 fields (unsigned 64-bit integers).\n"). -spec fixed64(integer()) -> decoder(integer()). fixed64(Number) -> field(Number, fun fixed64_int_field/1). -file("src/protozoa/decode.gleam", 576). ?DOC(" Decoder for sfixed32 fields (signed 32-bit integers).\n"). -spec sfixed32(integer()) -> decoder(integer()). sfixed32(Number) -> field(Number, fun sfixed32_field/1). -file("src/protozoa/decode.gleam", 581). ?DOC(" Decoder for sfixed64 fields (signed 64-bit integers).\n"). -spec sfixed64(integer()) -> decoder(integer()). sfixed64(Number) -> field(Number, fun sfixed64_field/1). -file("src/protozoa/decode.gleam", 586). ?DOC(" Decoder for repeated int32 fields.\n"). -spec repeated_int32(integer()) -> decoder(list(integer())). repeated_int32(Number) -> repeated_field(Number, fun varint_field/1). -file("src/protozoa/decode.gleam", 591). ?DOC(" Decoder for repeated string fields.\n"). -spec repeated_string(integer()) -> decoder(list(binary())). repeated_string(Number) -> repeated_field(Number, fun string_field/1). -file("src/protozoa/decode.gleam", 625). ?DOC( " Build a decoder using Gleam's use syntax.\n" " This allows for composing multiple field decoders into a single decoder.\n" " Collects all errors from both decoder stages.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " use name <- decode.then(decode.string(1))\n" " use age <- decode.then(decode.int32(2))\n" " decode.success(Person(name: name, age: age))\n" " ```\n" ). -spec then(decoder(OAQ), fun((OAQ) -> decoder(OAS))) -> decoder(OAS). then(Decoder, Next) -> {decoder, fun(Fields) -> {decoder, F} = Decoder, case F(Fields) of {ok, Value} -> {decoder, G} = Next(Value), G(Fields); {error, Errors} -> {error, Errors} end end}. -file("src/protozoa/decode.gleam", 646). ?DOC( " Transform the result of a decoder using a mapping function.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " decode.int32(1)\n" " |> decode.map(fn(x) { x * 2 })\n" " ```\n" ). -spec map(decoder(OAV), fun((OAV) -> OAX)) -> decoder(OAX). map(Decoder, F) -> {decoder, fun(Fields) -> {decoder, G} = Decoder, gleam@result:'try'(G(Fields), fun(Value) -> {ok, F(Value)} end) end}. -file("src/protozoa/decode.gleam", 662). ?DOC( " Build a dictionary from a list of fields for O(1) lookup performance.\n" " Fields with the same number are grouped together in a list.\n" ). -spec build_field_dict(list(field())) -> gleam@dict:dict(integer(), list(field())). build_field_dict(Fields) -> gleam@list:fold( Fields, maps:new(), fun(Acc, Field) -> gleam@dict:upsert( Acc, erlang:element(2, Field), fun(Existing) -> case Existing of {some, Fields@1} -> lists:append(Fields@1, [Field]); none -> [Field] end end ) end ). -file("src/protozoa/decode.gleam", 722). -spec decode_varint_helper(bitstring(), integer(), integer()) -> {ok, {integer(), bitstring()}} | {error, decode_error()}. decode_varint_helper(Data, Value, Shift) -> case Data of <<>> -> {error, {decode_error, <<"more varint data"/utf8>>, <<"unexpected end of data"/utf8>>, []}}; <> -> New_value = begin _pipe = Value, erlang:'bor'( _pipe, begin _pipe@1 = erlang:'band'(Byte, 16#7F), erlang:'bsl'(_pipe@1, Shift) end ) end, case erlang:'band'(Byte, 16#80) of 0 -> {ok, {New_value, Rest}}; _ -> decode_varint_helper(Rest, New_value, Shift + 7) end; _ -> {error, {decode_error, <<"valid varint data"/utf8>>, <<"invalid varint data"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 718). -spec decode_varint_raw(bitstring()) -> {ok, {integer(), bitstring()}} | {error, decode_error()}. decode_varint_raw(Data) -> decode_varint_helper(Data, 0, 0). -file("src/protozoa/decode.gleam", 745). -spec decode_fixed32_raw(bitstring()) -> {ok, {bitstring(), bitstring()}} | {error, decode_error()}. decode_fixed32_raw(Data) -> case Data of <> -> {ok, {Value, Rest}}; _ -> {error, {decode_error, <<"4 bytes for fixed32"/utf8>>, <<"insufficient data"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 754). -spec decode_fixed64_raw(bitstring()) -> {ok, {bitstring(), bitstring()}} | {error, decode_error()}. decode_fixed64_raw(Data) -> case Data of <> -> {ok, {Value, Rest}}; _ -> {error, {decode_error, <<"8 bytes for fixed64"/utf8>>, <<"insufficient data"/utf8>>, []}} end. -file("src/protozoa/decode.gleam", 763). -spec decode_length_delimited_raw(bitstring()) -> {ok, {bitstring(), bitstring()}} | {error, decode_error()}. decode_length_delimited_raw(Data) -> gleam@result:'try'( decode_varint_raw(Data), fun(_use0) -> {Length, Rest} = _use0, case erlang:byte_size(Rest) >= Length of true -> Bytes_to_take = Length * 8, case Rest of <> -> {ok, {Value, Rest@1}}; _ -> {error, {decode_error, <<"sufficient bytes for length-delimited field"/utf8>>, <<"insufficient data"/utf8>>, []}} end; false -> {error, {decode_error, <<"sufficient bytes for length-delimited field"/utf8>>, <<"insufficient data"/utf8>>, []}} end end ). -file("src/protozoa/decode.gleam", 686). -spec decode_field(bitstring()) -> {ok, {field(), bitstring()}} | {error, decode_error()}. decode_field(Data) -> gleam@result:'try'( decode_varint_raw(Data), fun(_use0) -> {Tag, Rest1} = _use0, Field_number = protozoa@wire:get_field_number(Tag), gleam@result:'try'( begin _pipe = protozoa@wire:get_wire_type(Tag), gleam@result:map_error( _pipe, fun(_) -> {decode_error, <<"valid wire type"/utf8>>, <<"invalid wire type"/utf8>>, []} end ) end, fun(Wire_type) -> case Wire_type of varint -> gleam@result:'try'( decode_varint_raw(Rest1), fun(_use0@1) -> {Value, Rest2} = _use0@1, {ok, {{field, Field_number, Wire_type, <>}, Rest2}} end ); fixed64 -> gleam@result:'try'( decode_fixed64_raw(Rest1), fun(_use0@2) -> {Value@1, Rest2@1} = _use0@2, {ok, {{field, Field_number, Wire_type, Value@1}, Rest2@1}} end ); length_delimited -> gleam@result:'try'( decode_length_delimited_raw(Rest1), fun(_use0@3) -> {Value@2, Rest2@2} = _use0@3, {ok, {{field, Field_number, Wire_type, Value@2}, Rest2@2}} end ); fixed32 -> gleam@result:'try'( decode_fixed32_raw(Rest1), fun(_use0@4) -> {Value@3, Rest2@3} = _use0@4, {ok, {{field, Field_number, Wire_type, Value@3}, Rest2@3}} end ); _ -> {error, {decode_error, <<"supported wire type"/utf8>>, <<"unsupported wire type"/utf8>>, []}} end end ) end ). -file("src/protozoa/decode.gleam", 673). -spec decode_fields(bitstring(), list(field())) -> {ok, list(field())} | {error, decode_error()}. decode_fields(Data, Acc) -> case Data of <<>> -> {ok, lists:reverse(Acc)}; _ -> gleam@result:'try'( decode_field(Data), fun(_use0) -> {Field, Rest} = _use0, decode_fields(Rest, [Field | Acc]) end ) end. -file("src/protozoa/decode.gleam", 656). -spec decode_message(bitstring()) -> {ok, list(field())} | {error, decode_error()}. decode_message(Data) -> decode_fields(Data, []). -file("src/protozoa/decode.gleam", 98). ?DOC( " Run a decoder on a BitArray containing Protocol Buffer data.\n" " Returns either the decoded value or a list of all errors encountered.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " let decoder = field(1, varint_field)\n" " run(<<8, 42>>, decoder) // Decodes field 1 with value 42\n" " ```\n" ). -spec run(bitstring(), decoder(NWU)) -> {ok, NWU} | {error, list(decode_error())}. run(Data, Decoder) -> gleam@result:'try'( begin _pipe = decode_message(Data), gleam@result:map_error(_pipe, fun(Err) -> [Err] end) end, fun(Fields) -> Field_dict = build_field_dict(Fields), {decoder, F} = Decoder, F(Field_dict) end ). -file("src/protozoa/decode.gleam", 470). ?DOC(false). -spec message_field(field(), decoder(NZH)) -> {ok, NZH} | {error, decode_error()}. message_field(Field, Decoder) -> gleam@result:'try'( bytes_field(Field), fun(Bytes) -> gleam@result:'try'( begin _pipe = decode_message(Bytes), gleam@result:map_error(_pipe, fun(Err) -> Err end) end, fun(Inner_fields) -> Field_dict = build_field_dict(Inner_fields), {decoder, F} = Decoder, case F(Field_dict) of {ok, Value} -> {ok, Value}; {error, [First_error | _]} -> {error, First_error}; {error, []} -> {error, {decode_error, <<"valid message data"/utf8>>, <<"empty error list"/utf8>>, []}} end end ) end ). -file("src/protozoa/decode.gleam", 596). ?DOC(" Decoder for nested message fields.\n"). -spec nested_message(integer(), decoder(OAI)) -> decoder(OAI). nested_message(Number, Decoder) -> field(Number, fun(F) -> message_field(F, Decoder) end). -file("src/protozoa/decode.gleam", 601). ?DOC(" Decoder for optional nested message fields.\n"). -spec optional_nested_message(integer(), decoder(OAL)) -> decoder({ok, OAL} | {error, nil}). optional_nested_message(Number, Decoder) -> optional_field(Number, fun(F) -> message_field(F, Decoder) end). -file("src/protozoa/decode.gleam", 804). ?DOC( " Decodes a zigzag-encoded integer back to its signed value.\n" " Zigzag encoding is used for sint32 and sint64 fields to efficiently\n" " encode negative numbers.\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " decode_zigzag(0) // Returns 0\n" " decode_zigzag(1) // Returns -1\n" " decode_zigzag(2) // Returns 1\n" " ```\n" ). -spec decode_zigzag(integer()) -> integer(). decode_zigzag(Value) -> case erlang:'band'(Value, 1) of 0 -> erlang:'bsr'(Value, 1); _ -> - erlang:'bsr'(Value + 1, 1) end. -file("src/protozoa/decode.gleam", 818). ?DOC( " Decoder for sint32 fields (signed 32-bit integers with zigzag encoding).\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " sint32(1) // Decodes field 1 as a zigzag-encoded int32\n" " ```\n" ). -spec sint32(integer()) -> decoder(integer()). sint32(Number) -> {decoder, fun(Fields) -> {decoder, F@1} = field( Number, fun(F) -> gleam@result:'try'( varint_field(F), fun(Value) -> {ok, decode_zigzag(Value)} end ) end ), F@1(Fields) end}. -file("src/protozoa/decode.gleam", 836). ?DOC( " Decoder for sint64 fields (signed 64-bit integers with zigzag encoding).\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " sint64(1) // Decodes field 1 as a zigzag-encoded int64\n" " ```\n" ). -spec sint64(integer()) -> decoder(integer()). sint64(Number) -> {decoder, fun(Fields) -> {decoder, F@1} = field( Number, fun(F) -> gleam@result:'try'( varint_field(F), fun(Value) -> {ok, decode_zigzag(Value)} end ) end ), F@1(Fields) end}.