UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

139 lines (138 loc) 3.71 kB
/** * 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; };