From abd66e4f2fd96b0194d1f81929cca13382a5653c Mon Sep 17 00:00:00 2001 From: Gavin Morrow Date: Fri, 19 Sep 2025 20:34:46 -0400 Subject: [PATCH] Create protobuf `Decoder` --- src/protobuf_decode_gleam.gleam | 14 ++++++++++++++ test/protobuf_decode_gleam_test.gleam | 27 +++++++++++++-------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/protobuf_decode_gleam.gleam b/src/protobuf_decode_gleam.gleam index 7bd65fb..a6861be 100644 --- a/src/protobuf_decode_gleam.gleam +++ b/src/protobuf_decode_gleam.gleam @@ -14,6 +14,20 @@ pub fn decode( decode.run(data, decoder) |> result.map_error(UnableToDecode) } +pub fn decoder( + using decoder: fn() -> Decoder(t), + named name: String, + default default: t, +) -> Decoder(t) { + use bits <- decode.then(decode.bit_array) + + let value = decode(from: bits, using: decoder()) + case value { + Ok(value) -> decode.success(value) + Error(_) -> decode.failure(default, name) + } +} + type WireType { VarInt I64 diff --git a/test/protobuf_decode_gleam_test.gleam b/test/protobuf_decode_gleam_test.gleam index 776ef60..9858708 100644 --- a/test/protobuf_decode_gleam_test.gleam +++ b/test/protobuf_decode_gleam_test.gleam @@ -1,7 +1,9 @@ import gleam/dynamic/decode.{type Decoder} import gleam/option import gleeunit -import protobuf_decode_gleam.{decode, decode_fixed, decode_uint} +import protobuf_decode_gleam.{ + decode, decode_fixed, decode_string, decode_uint, decoder, +} import simplifile as file pub fn main() -> Nil { @@ -12,20 +14,17 @@ type Person { Person(id: Int, age: Int, score: Int, self: option.Option(Person), day: Int) } -fn person_decoder() -> Decoder(Person) { - let person_inner_decoder = { - use bits <- decode.then(decode.bit_array) +const default_person = Person( + id: 0, + age: 0, + score: 0, + self: option.None, + day: 0, +) - let person = decode(from: bits, using: person_decoder()) - case person { - Ok(person) -> decode.success(person) - Error(_) -> - decode.failure( - Person(id: 0, age: 0, score: 0, self: option.None, day: 0), - "Person", - ) - } - } +fn person_decoder() -> Decoder(Person) { + let person_inner_decoder = + decoder(using: person_decoder, named: "Person", default: default_person) use id <- decode.field(3, decode_fixed(64)) use age <- decode.field(1, decode_uint()) -- 2.51.2