import birl import gleam/list import gleeunit import gleeunit/should import ieee_float.{finite, nan, positive_infinity} import kmer.{ type DecodeResult, type DecodedValue, Array, Boolean, Bytes, DateTime, Float, Integer, Map, Null, String, Undefined, } pub fn main() { gleeunit.main() } fn table_test_decode(test_case: BitArray, expected: DecodedValue) { kmer.decode(test_case) |> is_value(expected) } fn is_value(val: DecodeResult, expected: DecodedValue) { should.be_ok(val) |> should.equal(#(expected, <<>>)) } pub fn decode_immediate_int_test() { [ // Small integers under 24 #(<<0>>, Integer(0)), #(<<10>>, Integer(10)), #(<<23>>, Integer(23)), ] |> table_fn(table_test_decode) } pub fn decode_int_test() { [ // 1-byte length (Maj.arg 24) #(<<24, 24>>, Integer(24)), #(<<24, 100>>, Integer(100)), // 2-byte length (Maj.arg 25) #(<<25, 1234:16>>, Integer(1234)), #(<<25, 12_345:16>>, Integer(12_345)), // 3-byte length (Maj.arg 26) #(<<26, 1_234_567:32>>, Integer(1_234_567)), #(<<26, 999_999_999:32>>, Integer(999_999_999)), // 4-byte length (Maj.arg 27) #(<<27, 2_099_210_021_019_898_881:64>>, Integer(2_099_210_021_019_898_881)), #(<<27, 3:64>>, Integer(3)), ] |> table_fn(table_test_decode) } pub fn decode_negative_int_test() { [ // Immediate negative (under 25) #(<<1:3, 0:5>>, Integer(-1)), #(<<1:3, 8:5>>, Integer(-9)), #(<<1:3, 23:5>>, Integer(-24)), // 1-byte length (Maj.arg 24) #(<<1:3, 24:5, 24:8>>, Integer(-25)), #(<<1:3, 24:5, 100:8>>, Integer(-101)), // 2-byte length (Maj.arg 25) #(<<1:3, 25:5, 1234:16>>, Integer(-1235)), #(<<1:3, 25:5, 12_345:16>>, Integer(-12_346)), // 3-byte length (Maj.arg 26) #(<<1:3, 26:5, 1_234_567:32>>, Integer(-1_234_568)), #(<<1:3, 26:5, 999_999_999:32>>, Integer(-1_000_000_000)), // 4-byte length (Maj.arg 27) #( <<1:3, 27:5, 2_099_210_021_019_898_881:64>>, Integer(-2_099_210_021_019_898_882), ), #(<<1:3, 27:5, 3:64>>, Integer(-4)), ] |> table_fn(table_test_decode) } pub fn decode_simple_test() { [ #(<<7:3, 20:5>>, Boolean(False)), #(<<7:3, 21:5>>, Boolean(True)), #(<<7:3, 22:5>>, Null), #(<<7:3, 23:5>>, Undefined), ] |> table_fn(table_test_decode) } pub fn decode_float_test() { [ #(<<7:3, 25:5, 0x0000:16>>, Float(finite(0.0))), #(<<7:3, 25:5, 0x3c00:16>>, Float(finite(1.0))), #(<<7:3, 25:5, 0x3e00:16>>, Float(finite(1.5))), #(<<7:3, 25:5, 0xc400:16>>, Float(finite(-4.0))), #(<<7:3, 25:5, 0x7c00:16>>, Float(positive_infinity())), #(<<7:3, 25:5, 0x7e00:16>>, Float(nan())), #(<<7:3, 26:5, 0x47c35000:32>>, Float(finite(100_000.0))), #(<<7:3, 27:5, 0x3ff199999999999a:64>>, Float(finite(1.1))), #(<<7:3, 27:5, 0x7e37e43c8800759c:64>>, Float(finite(1.0e300))), ] |> table_fn(table_test_decode) } pub fn decode_bytestring_test() { [ #( <<2:3, 9:5, 10, 11, 12, 13, 14, 15, 16, 17, 18>>, Bytes(<<10, 11, 12, 13, 14, 15, 16, 17, 18>>), ), #( <<2:3, 24:5, 8:8, 11, 12, 13, 14, 15, 16, 17, 18>>, Bytes(<<11, 12, 13, 14, 15, 16, 17, 18>>), ), ] |> table_fn(table_test_decode) } pub fn decode_string_test() { [ #(<<3:3, 11:5, "Hello world">>, String("Hello world")), #( <<3:3, 24:5, 25:8, "perché siamo fatti così">>, String("perché siamo fatti così"), ), ] |> table_fn(table_test_decode) } pub fn decode_list_test() { [ #( <<4:3, 5:5, 1, 2, 3, 4, 5>>, Array([Integer(1), Integer(2), Integer(3), Integer(4), Integer(5)]), ), #( <<4:3, 24:5, 3:8, 3:3, 11:5, "Hello world", 1:3, 24:5, 123:8, 3>>, Array([String("Hello world"), Integer(-124), Integer(3)]), ), ] |> table_fn(table_test_decode) } pub fn decode_map_test() { [ #( <<5:3, 2:5, 3:3, 8:5, "test-key", 5, 3:3, 5:5, "other", 10>>, Map([#(String("test-key"), Integer(5)), #(String("other"), Integer(10))]), ), #( <<5:3, 24:5, 4:8, 1, 2, 3, 4, 5, 6, 7, 8>>, Map([ #(Integer(1), Integer(2)), #(Integer(3), Integer(4)), #(Integer(5), Integer(6)), #(Integer(7), Integer(8)), ]), ), ] |> table_fn(table_test_decode) } pub fn decode_time_test() { let assert Ok(textdate_example) = birl.parse("2024-11-30T21:56:27Z") [ // ISO8601 date #( <<6:3, 0:5, 3:3, 20:5, "2024-11-30T21:56:27Z">>, DateTime(textdate_example), ), // Unixtime #( <<6:3, 1:5, 1:3, 26:5, 1_733_005_876:32>>, DateTime(birl.from_unix(1_733_005_876)), ), #( <<6:3, 1:5, 7:3, 27:5, 0x41D9D2E48D200000:64>>, DateTime(birl.from_unix_milli(1_733_005_876_500)), ), ] |> table_fn(table_test_decode) } fn table_fn(tests: List(#(a, b)), test_fn: fn(a, b) -> Nil) { list.map(tests, fn(t) { let #(test_case, expected) = t test_fn(test_case, expected) }) }