From b48f97d1c3fa582a5b35e3d7f134e97077f41d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20BECHER?= Date: Thu, 9 May 2024 16:26:50 +0200 Subject: [PATCH] add empty BitArray implementation --- src/bitarray.ts | 147 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 124 insertions(+), 23 deletions(-) diff --git a/src/bitarray.ts b/src/bitarray.ts index bdc6d99..5819004 100644 --- a/src/bitarray.ts +++ b/src/bitarray.ts @@ -1,5 +1,5 @@ import { join } from "./collector.js"; -import { Enumerable, arrayLike, sequence } from "./sync.js"; +import { arrayLike, sequence } from "./sync.js"; import { asArray, isDefined } from "./utils.js"; export interface BitArray extends Iterable { @@ -81,28 +81,6 @@ function* getBytes(bits: Iterable) { } } -export namespace BitArray { - export function create(length: number): BitArray { - return new BitArrayImpl(length); - } - - export function from(bits: Iterable): BitArray { - const arr = asArray(bits); - const result = create(arr.length); - - let i = 0; - for (const bit of arr) { - result.set(i++, bit); - } - - return result; - } - - export function of(...bits: boolean[]): BitArray { - return from(bits); - } -} - class BitArrayImpl implements BitArray { readonly #length: number; readonly #bits: Uint8Array; @@ -281,6 +259,100 @@ class BitArrayImpl implements BitArray { } } +class EmptyBitArray implements BitArray { + [Symbol.iterator](): Iterator { + return { + next: () => ({ done: true, value: undefined }) + }; + } + + get length() { + return 0; + } + + isFull() { + return false; + } + + isEmpty() { + return false; + } + + get(index: number): boolean { + throw new Error("BitArray has zero length"); + } + + set(index: number, value: boolean) { + throw new Error("BitArray has zero length"); + } + + fill(value: boolean) { } + + and(other: BitArray) { + if (other.length !== 0) { + throw new Error("The other BitArray does not have zero length"); + } + + return this; + } + + or(other: BitArray) { + if (other.length !== 0) { + throw new Error("The other BitArray does not have zero length"); + } + + return this; + } + + xor(other: BitArray) { + if (other.length !== 0) { + throw new Error("The other BitArray does not have zero length"); + } + + return this; + } + + not() { + return this; + } + + contains(other: BitArray) { + return false; + } + + intersects(other: BitArray) { + return false; + } + + slice(offset: number, length: number) { + if (offset > 0) { + throw new Error("offset > 0"); + } + + if (length > 0) { + throw new Error("length > 0"); + } + + return this; + } + + copy() { + return this; + } + + toArray(): boolean[] { + return []; + } + + equals(other: BitArray) { + return other === this || other && other.length === 0; + } + + toString() { + return ""; + } +} + class BitArraySlice implements BitArray { readonly #parent: BitArray; readonly #offset: number; @@ -428,3 +500,32 @@ class BitArraySlice implements BitArray { return sequence(this).select(bit => bit ? '1' : '0').collect(join()); } } + +const emptyBitArray = new EmptyBitArray(); + +export namespace BitArray { + export const EMPTY = emptyBitArray; + + export function create(length: number): BitArray { + if (length < 0) { + throw new Error("length < 0"); + } + + return length === 0 ? EMPTY : new BitArrayImpl(length); + } + + export function from(bits: Iterable): BitArray { + const arr = asArray(bits); + const result = create(arr.length); + + for (let i = 0; i < arr.length; i++) { + result.set(i, arr[i]); + } + + return result; + } + + export function of(...bits: boolean[]): BitArray { + return from(bits); + } +}