From 0cdca046c0df81a173082845c97c32015eb3eeb4 Mon Sep 17 00:00:00 2001 From: Hayleigh Thompson Date: Sat, 18 Jul 2026 21:03:14 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20cid=20type=20and=20conversion?= =?UTF-8?q?s.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/at/cid.gleam | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/at/cid.gleam diff --git a/src/at/cid.gleam b/src/at/cid.gleam new file mode 100644 index 0000000..c31819f --- /dev/null +++ b/src/at/cid.gleam @@ -0,0 +1,89 @@ +import at/internal/base32 +import gleam/dynamic/decode.{type Decoder} + +// TYPES ----------------------------------------------------------------------- + +pub opaque type Cid { + Cid( + version: Int, + codec: Int, + hash_type: Int, + hash_size: Int, + digest: BitArray, + ) +} + +// CONSTANTS ------------------------------------------------------------------- + +@internal +pub const zero = Cid( + version: 0, + codec: 0, + hash_type: 0, + hash_size: 0, + digest: <<>>, +) + +// CONSTRUCTORS ---------------------------------------------------------------- + +pub fn from_bit_array(bits: BitArray) -> Result(Cid, Nil) { + case bits { + <<1:8, codec:8, 0x12:8, 32:8, digest:bytes-size(32)>> -> + case codec { + 0x55 | 0x71 -> Ok(Cid(1, codec, 0x12, 32, digest)) + _ -> Error(Nil) + } + + _ -> Error(Nil) + } +} + +pub fn from_string(value: String) -> Result(Cid, Nil) { + case value { + "b" <> remaining -> + case base32.decode(remaining) { + Ok(bits) -> from_bit_array(bits) + Error(_) -> Error(Nil) + } + + _ -> Error(Nil) + } +} + +pub fn decoder() -> Decoder(Cid) { + decode.one_of(bits_decoder(), [string_decoder()]) +} + +fn bits_decoder() -> Decoder(Cid) { + use bits <- decode.then(decode.bit_array) + + case from_bit_array(bits) { + Ok(cid) -> decode.success(cid) + Error(_) -> decode.failure(zero, "Cid") + } +} + +fn string_decoder() -> Decoder(Cid) { + use string <- decode.then(decode.string) + + case from_string(string) { + Ok(cid) -> decode.success(cid) + Error(_) -> decode.failure(zero, "Cid") + } +} + +// CONVERSIONS ----------------------------------------------------------------- + +pub fn to_bit_array(cid: Cid) -> BitArray { + << + cid.version:8, + cid.codec:8, + cid.hash_type:8, + cid.hash_size:8, + cid.digest:bits, + >> +} + +pub fn to_string(cid: Cid) -> String { + "b" <> base32.encode(to_bit_array(cid), True) +} -- 2.51.2