functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
139 lines (138 loc) • 3.71 kB
JavaScript
/**
* MSb is most-significant bit first.
* ```
* - byte: 0x53 = 0b0101_0011
* - 0123_4567
* ```
* LSb is least-significant bit first.
* ```
* - byte: 0x53 = 0b0101_0011
* - 7654_3210
* ```
* @module
*/
import { log2, mask } from "../bigint/module.f.js";
import { flip } from "../function/module.f.js";
import { fold } from "../list/module.f.js";
/**
* An empty vector of bits.
*/
export const empty = 1n;
/**
* Calculates the length of the given vector of bits.
*/
export const length = log2;
/**
* Creates a vector of bits of the given `len` and the given unsigned integer.
*
* @example
*
* ```js
* const vec4 = vec(4n)
* const v0 = vec4(5n) // 0x15n = 0b1_0101
* const v1 = vec4(0x5FEn) // 0x1En = 0b1_1110
* ```
*/
export const vec = (len) => {
if (len <= 0n) {
return () => empty;
}
const stop = 1n << len;
const mask = stop - 1n;
return data => stop | (data & mask);
};
/**
* Creates an 8 bit vector from an unsigned integer.
*/
export const vec8 = vec(8n);
/**
* Returns the unsigned integer of the given vector by removing a stop bit.
*
* @example
*
* ```js
* const vector = vec(8n)(0x5n) // 0x105n
* const result = uint(vector); // result is 0x5n
* ```
*/
export const uint = (v) => v ^ (1n << length(v));
/**
* Implements operations for handling vectors in a least-significant-bit (LSb) first order.
*
* https://en.wikipedia.org/wiki/Bit_numbering#LSb_0_bit_numbering
*
* Usually associated with Little-Endian (LE) byte order.
*/
export const lsb = {
front: len => {
const m = mask(len);
return v => {
const result = v & m;
return result === v ? uint(v) : result;
};
},
removeFront: len => v => {
const r = v >> len;
return r === 0n ? empty : r;
},
popFront: len => {
const m = mask(len);
return v => {
const result = v & m;
return result === v ? [uint(v), empty] : [result, v >> len];
};
},
concat: a => {
const aLen = length(a);
const m = mask(aLen);
return b => (b << aLen) | (a & m);
},
};
/**
* Implements operations for handling vectors in a most-significant-bit (MSb) first order.
*
* https://en.wikipedia.org/wiki/Bit_numbering#MSb_0_bit_numbering
*
* Usually associated with Big-Endian (BE) byte order.
*/
export const msb = {
front: len => {
const m = mask(len);
return v => (v >> (length(v) - len)) & m;
},
removeFront: len => v => vec(length(v) - len)(v),
popFront: len => {
const m = mask(len);
return v => {
const d = length(v) - len;
return [(v >> d) & m, vec(d)(v)];
};
},
concat: flip(lsb.concat),
};
const appendU8 = ({ concat }) => (u8) => (a) => concat(a)(vec8(BigInt(u8)));
/**
* Converts a list of unsigned 8-bit integers to a bit vector.
*
* @param bo The bit order for the conversion
* @param list The list of unsigned 8-bit integers to be converted.
* @returns The resulting vector based on the provided bit order.
*/
export const u8ListToVec = (bo) => fold(appendU8(bo))(empty);
/**
* Converts a bit vector to a list of unsigned 8-bit integers based on the provided bit order.
*
* @param bitOrder The bit order for the conversion.
* @param v The vector to be converted.
* @returns A thunk that produces a list of unsigned 8-bit integers.
*/
export const u8List = ({ popFront }) => {
const f = (v) => () => {
if (v === empty) {
return null;
}
const [first, tail] = popFront(8n)(v);
return { first: Number(first), tail: f(tail) };
};
return f;
};