225 lines
5.1 KiB
JavaScript
225 lines
5.1 KiB
JavaScript
import {
|
|
toList,
|
|
Empty as $Empty,
|
|
prepend as listPrepend,
|
|
CustomType as $CustomType,
|
|
} from "../gleam.mjs";
|
|
import * as $bit_array from "../gleam/bit_array.mjs";
|
|
import * as $list from "../gleam/list.mjs";
|
|
import * as $string_tree from "../gleam/string_tree.mjs";
|
|
|
|
class Bytes extends $CustomType {
|
|
constructor($0) {
|
|
super();
|
|
this[0] = $0;
|
|
}
|
|
}
|
|
|
|
class Text extends $CustomType {
|
|
constructor($0) {
|
|
super();
|
|
this[0] = $0;
|
|
}
|
|
}
|
|
|
|
class Many extends $CustomType {
|
|
constructor($0) {
|
|
super();
|
|
this[0] = $0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Appends a bytes tree onto the end of another.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function append_tree(first, second) {
|
|
if (second instanceof Bytes) {
|
|
return new Many(toList([first, second]));
|
|
} else if (second instanceof Text) {
|
|
return new Many(toList([first, second]));
|
|
} else {
|
|
let trees = second[0];
|
|
return new Many(listPrepend(first, trees));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepends a bytes tree onto the start of another.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function prepend_tree(second, first) {
|
|
return append_tree(first, second);
|
|
}
|
|
|
|
/**
|
|
* Joins a list of bytes trees into a single one.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function concat(trees) {
|
|
return new Many(trees);
|
|
}
|
|
|
|
/**
|
|
* Create an empty `BytesTree`. Useful as the start of a pipe chaining many
|
|
* trees together.
|
|
*/
|
|
export function new$() {
|
|
return concat(toList([]));
|
|
}
|
|
|
|
/**
|
|
* Creates a new bytes tree from a string.
|
|
*
|
|
* Runs in constant time when running on Erlang.
|
|
* Runs in linear time otherwise.
|
|
*/
|
|
export function from_string(string) {
|
|
return new Text($string_tree.from_string(string));
|
|
}
|
|
|
|
/**
|
|
* Prepends a string onto the start of a bytes tree.
|
|
*
|
|
* Runs in constant time when running on Erlang.
|
|
* Runs in linear time with the length of the string otherwise.
|
|
*/
|
|
export function prepend_string(second, first) {
|
|
return append_tree(from_string(first), second);
|
|
}
|
|
|
|
/**
|
|
* Appends a string onto the end of a bytes tree.
|
|
*
|
|
* Runs in constant time when running on Erlang.
|
|
* Runs in linear time with the length of the string otherwise.
|
|
*/
|
|
export function append_string(first, second) {
|
|
return append_tree(first, from_string(second));
|
|
}
|
|
|
|
/**
|
|
* Creates a new bytes tree from a string tree.
|
|
*
|
|
* Runs in constant time when running on Erlang.
|
|
* Runs in linear time otherwise.
|
|
*/
|
|
export function from_string_tree(tree) {
|
|
return new Text(tree);
|
|
}
|
|
|
|
function wrap_list(bits) {
|
|
return new Bytes(bits);
|
|
}
|
|
|
|
/**
|
|
* Creates a new bytes tree from a bit array.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function from_bit_array(bits) {
|
|
let _pipe = bits;
|
|
let _pipe$1 = $bit_array.pad_to_bytes(_pipe);
|
|
return wrap_list(_pipe$1);
|
|
}
|
|
|
|
/**
|
|
* Prepends a bit array to the start of a bytes tree.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function prepend(second, first) {
|
|
return append_tree(from_bit_array(first), second);
|
|
}
|
|
|
|
/**
|
|
* Appends a bit array to the end of a bytes tree.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function append(first, second) {
|
|
return append_tree(first, from_bit_array(second));
|
|
}
|
|
|
|
/**
|
|
* Joins a list of bit arrays into a single bytes tree.
|
|
*
|
|
* Runs in constant time.
|
|
*/
|
|
export function concat_bit_arrays(bits) {
|
|
let _pipe = bits;
|
|
let _pipe$1 = $list.map(_pipe, from_bit_array);
|
|
return concat(_pipe$1);
|
|
}
|
|
|
|
function to_list(loop$stack, loop$acc) {
|
|
while (true) {
|
|
let stack = loop$stack;
|
|
let acc = loop$acc;
|
|
if (stack instanceof $Empty) {
|
|
return acc;
|
|
} else {
|
|
let $ = stack.head;
|
|
if ($ instanceof $Empty) {
|
|
let remaining_stack = stack.tail;
|
|
loop$stack = remaining_stack;
|
|
loop$acc = acc;
|
|
} else {
|
|
let $1 = $.head;
|
|
if ($1 instanceof Bytes) {
|
|
let remaining_stack = stack.tail;
|
|
let rest = $.tail;
|
|
let bits = $1[0];
|
|
loop$stack = listPrepend(rest, remaining_stack);
|
|
loop$acc = listPrepend(bits, acc);
|
|
} else if ($1 instanceof Text) {
|
|
let remaining_stack = stack.tail;
|
|
let rest = $.tail;
|
|
let tree = $1[0];
|
|
let bits = $bit_array.from_string($string_tree.to_string(tree));
|
|
loop$stack = listPrepend(rest, remaining_stack);
|
|
loop$acc = listPrepend(bits, acc);
|
|
} else {
|
|
let remaining_stack = stack.tail;
|
|
let rest = $.tail;
|
|
let trees = $1[0];
|
|
loop$stack = listPrepend(trees, listPrepend(rest, remaining_stack));
|
|
loop$acc = acc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Turns a bytes tree into a bit array.
|
|
*
|
|
* Runs in linear time.
|
|
*
|
|
* When running on Erlang this function is implemented natively by the
|
|
* virtual machine and is highly optimised.
|
|
*/
|
|
export function to_bit_array(tree) {
|
|
let _pipe = toList([toList([tree])]);
|
|
let _pipe$1 = to_list(_pipe, toList([]));
|
|
let _pipe$2 = $list.reverse(_pipe$1);
|
|
return $bit_array.concat(_pipe$2);
|
|
}
|
|
|
|
/**
|
|
* Returns the size of the bytes tree's content in bytes.
|
|
*
|
|
* Runs in linear time.
|
|
*/
|
|
export function byte_size(tree) {
|
|
let _pipe = toList([toList([tree])]);
|
|
let _pipe$1 = to_list(_pipe, toList([]));
|
|
return $list.fold(
|
|
_pipe$1,
|
|
0,
|
|
(acc, bits) => { return $bit_array.byte_size(bits) + acc; },
|
|
);
|
|
}
|