Skip to content

Commit

Permalink
clean up cbor module, removing functions now already available in pre…
Browse files Browse the repository at this point in the history
…lude.
  • Loading branch information
KtorZ committed Aug 6, 2024
1 parent 205e8f9 commit d8f3e57
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 213 deletions.
38 changes: 3 additions & 35 deletions lib/aiken/bytearray.ak
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ test from_string_2() {

/// Add a byte element in front of a `ByteArray`. When the given byte is
/// greater than 255, it wraps-around. **PlutusV2 behavior** So 256 is mapped to 0, 257 to 1, and so
/// forth.
/// forth.
/// In PlutusV3 this will error instead of wrapping around.
///
/// ```aiken
Expand Down Expand Up @@ -422,44 +422,12 @@ pub fn to_hex(self: ByteArray) -> String {
|> builtin.decode_utf8
}

// Construct an hex string in reverse order, from the back. The 'builder' is an
// accumulator. It works fast because `index_bytearray` follows a constant-time cost
// model
fn encode_base16(bytes: ByteArray, ix: Int, builder: ByteArray) -> ByteArray {
if ix < 0 {
builder
} else {
let byte = builtin.index_bytearray(bytes, ix)
let msb = byte / 16
let lsb = byte % 16
encode_base16(
bytes,
ix - 1,
builtin.cons_bytearray(
msb + if msb < 10 {
48
} else {
87
},
builtin.cons_bytearray(
lsb + if lsb < 10 {
48
} else {
87
},
builder,
),
),
)
}
}

test to_hex_1() {
to_hex("Hello world!") == @"48656c6c6f20776f726c6421"
to_hex("Hello world!") == @"48656C6C6F20776F726C6421"
}

test to_hex_2() {
to_hex("The quick brown fox jumps over the lazy dog") == @"54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
to_hex("The quick brown fox jumps over the lazy dog") == @"54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67"
}

/// Checks whether a bit (Most-Significant-Bit first) is set in the given 'ByteArray'.
Expand Down
181 changes: 3 additions & 178 deletions lib/aiken/cbor.ak
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use aiken/builtin.{
append_bytearray, choose_data, cons_bytearray, decode_utf8, index_bytearray,
length_of_bytearray, quotient_integer, remainder_integer, serialise_data,
un_b_data, un_constr_data, un_i_data, un_list_data, un_map_data,
}
use aiken/list
use aiken
use aiken/builtin.{decode_utf8, serialise_data}

/// Serialise any value to binary, encoding using [CBOR](https://www.rfc-editor.org/rfc/rfc8949).
///
Expand Down Expand Up @@ -88,181 +84,10 @@ test serialise_9() {
/// diagnostic(None) == "122([])"
/// ```
pub fn diagnostic(self: Data) -> String {
do_diagnostic(self, #"")
aiken.diagnostic(self, #"")
|> decode_utf8
}

/// UTF-8 lookup table. Comes in handy to decipher the code below.
///
/// | Symbol | Decimal | Hex |
/// | --- | --- | --- |
/// | | 32 | 0x20 |
/// | ' | 39 | 0x27 |
/// | ( | 40 | 0x28 |
/// | ) | 41 | 0x29 |
/// | , | 44 | 0x2c |
/// | 0 | 48 | 0x30 |
/// | : | 58 | 0x3a |
/// | A | 65 | 0x41 |
/// | [ | 91 | 0x5b |
/// | ] | 93 | 0x5d |
/// | _ | 95 | 0x5f |
/// | h | 104 | 0x68 |
/// | { | 123 | 0x7b |
/// | } | 125 | 0x7d |
fn do_diagnostic(self: Data, builder: ByteArray) -> ByteArray {
choose_data(
self,
{
// -------- Constr
let Pair(constr, fields) = un_constr_data(self)

// NOTE: This is fundamentally the same logic for serializing list. However, the compiler
// doesn't support mutual recursion just yet, so we can't extract that logic in a separate
// function.
//
// See [aiken-lang/aiken#389](https://github.com/aiken-lang/aiken/pull/389)
let builder =
when fields is {
[] -> append_bytearray(#"5b5d29", builder)
_ -> {
let (_, bytes) =
list.foldr(
fields,
(#"5d", append_bytearray(#"29", builder)),
fn(e: Data, st: (ByteArray, ByteArray)) {
(#"2c20", do_diagnostic(e, append_bytearray(st.1st, st.2nd)))
},
)
append_bytearray(#"5b5f20", bytes)
}
}

let constr_tag =
if constr < 7 {
121 + constr
} else if constr < 128 {
1280 + constr - 7
} else {
fail @"What are you doing? No I mean, seriously."
}

builder
|> append_bytearray(#"28", _)
|> from_int(constr_tag, _)
},
{
// -------- Map

let elems = un_map_data(self)
when elems is {
[] -> append_bytearray(#"7b7d", builder)
_ -> {
let (_, bytes) =
list.foldr(
elems,
(#"207d", builder),
fn(e: Pair<Data, Data>, st: (ByteArray, ByteArray)) {
let value =
do_diagnostic(e.2nd, append_bytearray(st.1st, st.2nd))
(
#"2c20",
do_diagnostic(e.1st, append_bytearray(#"3a20", value)),
)
},
)
append_bytearray(#"7b5f20", bytes)
}
}
},
{
// -------- List

let elems = un_list_data(self)
when elems is {
[] -> append_bytearray(#"5b5d", builder)
_ -> {
let (_, bytes) =
list.foldr(
elems,
(#"5d", builder),
fn(e: Data, st: (ByteArray, ByteArray)) {
(#"2c20", do_diagnostic(e, append_bytearray(st.1st, st.2nd)))
},
)
append_bytearray(#"5b5f20", bytes)
}
}
},
// -------- Integer
self
|> un_i_data
|> from_int(builder),
{
// -------- ByteArray
let bytes = un_b_data(self)

bytes
|> encode_base16(
length_of_bytearray(bytes) - 1,
append_bytearray(#"27", builder),
)
|> append_bytearray(#"6827", _)
},
)
}

fn encode_base16(bytes: ByteArray, ix: Int, builder: ByteArray) -> ByteArray {
if ix < 0 {
builder
} else {
let byte = index_bytearray(bytes, ix)
let msb = byte / 16
let lsb = byte % 16
let builder =
cons_bytearray(
msb + if msb < 10 {
48
} else {
55
},
cons_bytearray(
lsb + if lsb < 10 {
48
} else {
55
},
builder,
),
)
encode_base16(bytes, ix - 1, builder)
}
}

fn from_int(i: Int, digits: ByteArray) -> ByteArray {
if i == 0 {
append_bytearray(#"30", digits)
} else if i < 0 {
append_bytearray(#"2d", from_int(-i, digits))
} else {
do_from_int(
quotient_integer(i, 10),
cons_bytearray(remainder_integer(i, 10) + 48, digits),
)
}
}

fn do_from_int(i: Int, digits: ByteArray) -> ByteArray {
if i <= 0 {
digits
} else {
do_from_int(
quotient_integer(i, 10),
cons_bytearray(remainder_integer(i, 10) + 48, digits),
)
}
}

test diagnostic_1() {
diagnostic(42) == @"42"
}
Expand Down

0 comments on commit d8f3e57

Please sign in to comment.