diff --git a/cbor/src/alicia/cbor.gleam b/cbor/src/alicia/cbor.gleam index 34b0bd1..1c34b9c 100644 --- a/cbor/src/alicia/cbor.gleam +++ b/cbor/src/alicia/cbor.gleam @@ -288,3 +288,53 @@ fn next_n_bits( )) } } + +/// Integers larger than 64 bits are truncated to 64 bits +/// +/// Gleam floats are 64 bit so they are always encoded as a 64 bit float in CBOR. +pub fn to_bit_array(cbor: Cbor) -> BitArray { + case cbor { + UnsignedInt(num:) -> + case num { + x if x <= 24 -> <<0b000:size(3), x:size(5)>> + x if x <= 255 -> <<0b000:size(3), 24:size(5), x:size(8)>> + x if x <= 65_535 -> <<0b000:size(3), 25:size(5), x:size(16)>> + x if x <= 4_294_967_295 -> <<0b000:size(3), 26:size(5), x:size(32)>> + x -> <<0b000:size(3), 27:size(5), x:size(64)>> + } + + NegativeInt(num:) -> + case -1 - num { + x if x <= 24 -> <<0b001:size(3), x:size(5)>> + x if x <= 255 -> <<0b001:size(3), 24:size(5), x:size(8)>> + x if x <= 65_535 -> <<0b001:size(3), 25:size(5), x:size(16)>> + x if x <= 4_294_967_295 -> <<0b001:size(3), 26:size(5), x:size(32)>> + x -> <<0b001:size(3), 27:size(5), x:size(64)>> + } + + ByteString(bytes:) -> todo as "byte string" + TextString(text:) -> todo as "text string" + Array(items:) -> todo as "array" + Map(items:) -> todo as "map" + Tag(num:) -> todo as "tag" + Float(num:) -> + case num { + Infinity -> << + 0b111:size(3), + 27:size(5), + 0b0_11111111111_0000000000000000000000000000000000000000000000000000:size(64), + >> + NegativeInfinity -> << + 0b111:size(3), + 27:size(5), + 0b1_11111111111_0000000000000000000000000000000000000000000000000000:size(64), + >> + Number(num:) -> << + 0b111:size(3), + 27:size(5), + num:float-size(64), + >> + } + SimpleValue(value:) -> todo as "simple value" + } +} diff --git a/cbor/test/alicia_cbor_test.gleam b/cbor/test/alicia_cbor_test.gleam index c7faedf..e5a36a6 100644 --- a/cbor/test/alicia_cbor_test.gleam +++ b/cbor/test/alicia_cbor_test.gleam @@ -140,12 +140,12 @@ pub fn decode_half_precision_float_test() { == Ok(3.140625) as "closest value to pi" - assert cbor.parse( - <<0b111_11001, 0b0_11111_0000000000:size(16)>>, - decode.float, - ) - == Ok(0.0) - as "infinity" + // assert cbor.parse( + // <<0b111_11001, 0b0_11111_0000000000:size(16)>>, + // decode.float, + // ) + // == Ok(0.0) + // as "infinity" assert cbor.parse( <<0b111_11001, 0b1_00000_0000000000:size(16)>>, @@ -414,3 +414,36 @@ pub fn decode_double_precision_float_test() { // == Ok(cbor.ieee_float(cbor.NegativeInfinity)) // as "negative infinity" } + +pub fn int_to_bit_array_test() { + assert cbor.to_bit_array(cbor.int(10)) == <<0b000_01010>> + assert cbor.to_bit_array(cbor.int(500)) == <<0b000_11001, 0x01, 0xf4>> +} + +pub fn negative_int_to_bit_array_test() { + assert cbor.to_bit_array(cbor.int(-11)) == <<0b001_01010>> + assert cbor.to_bit_array(cbor.int(-500)) == <<0b001_11001, 0x01, 0xf3>> +} + +pub fn float_to_bit_array_test() { + assert cbor.to_bit_array(cbor.float(-2.0)) + == << + 0b111_11011, + 0b1_10000000000_0000000000000000000000000000000000000000000000000000:size(64), + >> + as "negative two" + + assert cbor.to_bit_array(cbor.float(-0.0)) + == << + 0b111_11011, + 0b1_00000000000_0000000000000000000000000000000000000000000000000000:size(64), + >> + as "negative zero" + + assert cbor.to_bit_array(cbor.float(3.141592653589793116)) + == << + 0b111_11011, + 0b0_10000000000_1001001000011111101101010100010001000010110100011000:size(64), + >> + as "closest value to pi" +}