···11import gleam/bit_array
22import gleam/dynamic/decode.{type Decoder}
33+import gleam/list
3445import internal/util
56import protobuf_decode_gleam.{parse}
6788+fn single(of decoder: Decoder(t)) -> Decoder(t) {
99+ use values <- decode.then(decode.list(of: decoder))
1010+1111+ // I choose to use assert instead of `decode.failure` because the decode api
1212+ // requires passing a name and default value, which is clunky and would've
1313+ // added two parameters to this function.
1414+ // The only times this could fail are programmer error on my part or using
1515+ // this decoder on data not produced in a compatible way with this library.
1616+ let assert Ok(value) = list.last(values)
1717+ value |> decode.success
1818+}
1919+2020+// Allows the decoders to be used for either single or repeated fields
2121+fn single_or_raw(decoder: Decoder(t)) -> Decoder(t) {
2222+ decode.one_of(decoder, or: [single(of: decoder)])
2323+}
2424+725pub fn protobuf(
2626+ // Passed as a function so recursive decoders are easier
827 using decoder: fn() -> Decoder(t),
928 named name: String,
1029 default default: t,
1130) -> Decoder(t) {
1212- use bits <- decode.then(decode.bit_array)
3131+ use bits <- decode.then(single_or_raw(decode.bit_array))
13321433 let value = parse(from: bits, using: decoder())
1534 case value {
···1938}
20392140pub fn uint() -> Decoder(Int) {
2222- use bits <- decode.then(decode.bit_array)
4141+ use bits <- decode.then(single_or_raw(decode.bit_array))
2342 util.bit_array_to_uint(bits) |> decode.success
2443}
25442645pub fn fixed(size: Int) -> Decoder(Int) {
2727- use bits <- decode.then(decode.bit_array)
4646+ use bits <- decode.then(single_or_raw(decode.bit_array))
2847 let assert <<num:unsigned-little-size(size)>> = bits
2948 num |> decode.success
3049}
31503251pub fn string() -> Decoder(String) {
3333- use bits <- decode.then(decode.bit_array)
5252+ use bits <- decode.then(single_or_raw(decode.bit_array))
34533554 let str = bit_array.to_string(bits)
3655 case str {
+14-20
src/protobuf_decode_gleam.gleam
···50505151fn repeated_to_list(fields: List(Field)) -> dict.Dict(Dynamic, Dynamic) {
5252 let fields = {
5353- use fields, Field(key:, value:) <- list.fold(over: fields, from: dict.new())
5353+ // Every field is a list of values for two reasons:
5454+ // a) expanded repeated values are encoded as repeated fields
5555+ // b) if a non-repeating field is defined twice, then the last value should
5656+ // be considered the correct one. since the parser doesn't know which
5757+ // fields are repeating, it parses all fields as a list and then the
5858+ // decoders will handle choosing which value(s) to keep.
5959+ let acc: dict.Dict(Dynamic, List(Dynamic)) = dict.new()
6060+ use fields, Field(key:, value:) <- list.fold(over: fields, from: acc)
54615555- let value = case dict.get(fields, key) {
5656- Ok(existing_value) -> {
5757- // If the existing value is already a list, append to it
5858- // Otherwise, turn it into a list
5959- case decode.run(existing_value, decode.list(of: decode.dynamic)) {
6060- // NOTE: this puts the values in reverse order
6161- Ok(existing_values) -> [value, ..existing_values] |> dynamic.list
6262- Error(_) -> [value, existing_value] |> dynamic.list
6363- }
6464- }
6565- // If there is no existing value, don't change the value
6666- Error(Nil) -> value
6767- }
6868- dict.insert(into: fields, for: key, insert: value)
6262+ use existing_values <- dict.upsert(in: fields, update: key)
6363+ let existing_values = option.unwrap(existing_values, or: [])
6464+ [value, ..existing_values]
6965 }
70667167 // The repeated values must be in order, so un-reverse them here
7272- use _key, field <- dict.map_values(in: fields)
7373- case decode.run(field, decode.list(of: decode.dynamic)) {
7474- Ok(values) -> list.reverse(values) |> dynamic.list
7575- Error(_) -> field
7676- }
6868+ dict.map_values(in: fields, with: fn(_key, field) {
6969+ field |> list.reverse |> dynamic.list
7070+ })
7771}
78727973type DecodeResult(t) =