├── .editorconfig
├── .github
├── dependabot.yml
└── workflows
│ ├── ci.yml
│ └── style.yml
├── .gitignore
├── .markdownlint.jsonc
├── .prettierrc.json
├── .vscode
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── example
├── index.html
├── index.mjs
└── util.mjs
├── package-lock.json
├── package.json
├── scripts
└── postbuild.sh
├── src
└── bit-typedarray.ts
├── test
├── index.ts
├── suite.ts
└── test.ts
├── tsconfig.cjs.json
├── tsconfig.esm.json
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Full documentation can be found at editorconfig.org
2 | # This requires a plugin to be installed in the editor of choice
3 | # Link to info on plugins can be found here - http://editorconfig.org/#download
4 |
5 | root = true
6 |
7 | [*]
8 | charset = utf-8
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.{js,json,ts}]
14 | indent_style = space
15 | indent_size = 2
16 |
17 | [*.md]
18 | trim_trailing_whitespace = false
19 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
2 | # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
3 |
4 | version: 2
5 | updates:
6 |
7 | # Maintain dependencies for GitHub Actions
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | schedule:
11 | interval: "weekly"
12 |
13 | # Maintain dependencies for npm
14 | - package-ecosystem: "npm"
15 | directory: "/"
16 | schedule:
17 | interval: "weekly"
18 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on:
4 | push:
5 | paths-ignore: ['LICENSE', 'example/**', '**.md', '.*']
6 | pull_request:
7 | paths-ignore: ['LICENSE', 'example/**', '**.md', '.*']
8 |
9 | jobs:
10 | build:
11 | strategy:
12 | matrix:
13 | node-version: [20.x, 22.x, 24.x]
14 | os: [ubuntu-latest, macOS-latest] # , windows-latest
15 |
16 | runs-on: ${{ matrix.os }}
17 |
18 | steps:
19 | - uses: actions/checkout@v4
20 | - name: Use Node.js ${{ matrix.node-version }}
21 | uses: actions/setup-node@v4
22 | with:
23 | node-version: ${{ matrix.node-version }}
24 | cache: 'npm'
25 | - name: Install dependencies
26 | run: npm install # npm ci
27 | - run: npm run build --if-present
28 | - run: npm run test:ci
29 |
--------------------------------------------------------------------------------
/.github/workflows/style.yml:
--------------------------------------------------------------------------------
1 | name: conformance with Prettier
2 |
3 | on:
4 | push:
5 | paths: ['src/**.ts', '.prettierrc.json']
6 | pull_request:
7 | paths: ['src/**.ts', '.prettierrc.json']
8 |
9 | jobs:
10 | prettier:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | - uses: actions/setup-node@v4
15 | with:
16 | node-version: '18'
17 | cache: 'npm'
18 | - name: Install dependencies
19 | run: npm install # npm ci
20 | - name: Run prettier
21 | run: npm run style:check
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/*
2 | node_modules
3 |
--------------------------------------------------------------------------------
/.markdownlint.jsonc:
--------------------------------------------------------------------------------
1 | {
2 | "default": true,
3 | // keep VSCode default of no line-length limit
4 | // https://github.com/DavidAnson/vscode-markdownlint#markdownlintconfig
5 | "MD013": false,
6 | // those have been deprecated
7 | // https://github.com/DavidAnson/vscode-markdownlint#configure
8 | "MD002": false,
9 | "MD006": false
10 | }
11 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": true,
7 | "quoteProps": "as-needed",
8 | "trailingComma": "es5",
9 | "bracketSpacing": true,
10 | "bracketSameLine": false,
11 | "arrowParens": "always",
12 | "proseWrap": "preserve"
13 | }
14 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["esbenp.prettier-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | // From VSCode 1.67.1, this is the default
3 | "editor.bracketPairColorization.enabled": true,
4 | "editor.guides.bracketPairs": "active",
5 |
6 | "editor.defaultFormatter": "esbenp.prettier-vscode",
7 | "editor.formatOnSave": true
8 | }
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # @bitarray/typedarray ChangeLog
4 |
5 | ## v1.1.1
6 |
7 | _2022-08-07_
8 |
9 | - fix: path to .d.ts types file (for node v18?)
10 | - style: run prettier
11 | - chore: add .vscode for automatic prettier run
12 | - build: bump dependency version
13 |
14 | ## v1.1.0
15 |
16 | _2022-05-18_
17 |
18 | - feat: can now set bit values with booleans
19 | - fix: export type `bit`
20 | - chore: run github actions only when relevant
21 | - chore: explicit markdownlint rules
22 | - chore: move dependabot.yml to correct location
23 | - build: bump dependency version
24 |
25 | ## v1.0.3
26 |
27 | _2022-05-04_
28 |
29 | - build: move creation of package.json to postbuild
30 | - chore: add github actions for testing ([54c7aa9](https://github.com/swiing/Bit-TypedArray/commit/54c7aa9244bee3b1949a8b34ecccea45f1c69008)), styling ([8c9bdfa](https://github.com/swiing/Bit-TypedArray/commit/8c9bdfaba321b4987cb17eb151f06190aaf3c70e)) and dependabot ([0410dee](https://github.com/swiing/Bit-TypedArray/commit/0410deeeed0466bc651fc9af384337a6233ee0e5))
31 | - chore: update gitignore ([90749f1](https://github.com/swiing/Bit-TypedArray/commit/90749f12d45d79f1c23b8d587b93e5f4ffea412e))
32 | - chore: run example from script
33 | - chore: delete .gitattributes
34 | - style: add and run prettier
35 | - docs: reference WIP
36 | - fix: correct path and base url in example
37 |
38 | ## v1.0.2
39 |
40 | _2022-04-20_
41 |
42 | - build: make typescript happy
43 | - chore: move license to MIT
44 | - docs: cleanup readme
45 |
46 | ## v1.0.1
47 |
48 | _2022-04-03_
49 |
50 | - docs: improve badges
51 | - docs: improve readme
52 |
53 | ## v1.0.0
54 |
55 | _2022-04-02_
56 |
57 | ## v0.3.0
58 |
59 | _2022-03-30_
60 |
61 | ## v0.2.0
62 |
63 | _2021-04-21_
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022 swiing (www.github.com/swiing)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | # @bitarray/typedarray
10 |
11 | [](https://github.com/swiing/Bit-TypedArray#bitarraytypedarray)
12 |
13 | A bit array object exhibiting the interface of standard ecmascript [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray)'s.
14 |
15 | > :bulb: If you are looking for easily applying bitwise operations, check out [@bitarray/es6](https://github.com/swiing/BitArray), which builds on top of the present library. Here, we purposely stick to methods and properties described by the ecmascript specification (there are no bitwise operations on arrays specified by ecmascript).
16 |
17 | ## Rationale
18 |
19 | The ecmascript specification has introduced `TypedArray`s for `Int8`, `Uint8`, `Uint8Clamped`, `Int16`, `Uint16`, `Int32`, `Uint32`, `Float32`, `Float64`, `BigInt64` and `BigUint64` types.
20 |
21 | This library adds support for the `Bit` type. It provides a very memory-efficient means
22 | to store sequences of bits, while exposing the familiar, standard interface of typed arrays.
23 |
24 | ## Compatibility
25 |
26 | [](https://github.com/swiing/Bit-TypedArray#compatibility)
27 |
28 | The library uses a [Proxy](https://caniuse.com/?search=Proxy) object, which is an ES6 (aka ES2015) feature. It can **NOT** be polyfilled (to the extent it is used by the library).
29 |
30 | _Note: standard `TypedArray` is also a feature of ecmascript ES6._
31 |
32 | ## Installation
33 |
34 | [](https://www.npmjs.com/package/@bitarray/typedarray)
35 |
36 | ```sh
37 | npm install @bitarray/typedarray
38 | ```
39 |
40 | or
41 |
42 | ```sh
43 | yarn add @bitarray/typedarray
44 | ```
45 |
46 | ## Usage
47 |
48 | Usage is same as for any standard typed array. You may check the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) for details.
49 |
50 | ### Instantiating
51 |
52 | ```js
53 | import BitArray from "@bitarray/typedarray"
54 |
55 | const length = 32; // or whatever length value
56 | const bits = new BitArray(length);
57 |
58 | // Bit arrays can be created from iterables.
59 | // The following are all equivalent
60 |
61 | new BitArray("11001010");
62 | new BitArray([1, 1, 0, 0, 1, 0, 1, 0]);
63 | new BitArray([true, true, false, false, true, false, true, false]);
64 |
65 | BitArray.from("11001010");
66 | BitArray.from([1, 1, 0, 0, 1, 0, 1, 0]);
67 | BitArray.from([true, true, false, false, true, false, true, false]);
68 |
69 | BitArray.of(..."11001010");
70 | BitArray.of(1, 1, 0, 0, 1, 0, 1, 0);
71 | BitArray.of(true, true, false, false, true, false, true, false);
72 | ```
73 |
74 | ### Reading/writing values
75 |
76 | ```js
77 | bits[1]; // 0 by default
78 | bits[1] = 1;
79 | bits[1]; // 1
80 | bits.at(1); // 1
81 |
82 | // can also take boolean values
83 | // (will be coerced to bit)
84 | bits[1] = false;
85 | bits.at(1); // 0
86 | ```
87 |
88 | ### Iterating
89 |
90 | ```js
91 | for (let i=0; i { /* do something */ });
95 |
96 | for (let i in bits)
97 | // do something with bits[i]
98 |
99 | for (let bit of bits)
100 | // do something with bit
101 | ```
102 |
103 | ### Indexes & values
104 |
105 | ```js
106 | // indexes - following two are the same
107 | Object.keys(bits); // [0, 1, 2, ...]
108 | Object.getOwnPropertyNames(bits);
109 |
110 | // values
111 | Object.values(bits); // [0, 1, 0, 0, 0, ...]
112 |
113 | // entries
114 | Object.entries(bits); // [["0", 0], ["1", 1], ["2", 0], ["3", 0], ...]
115 | ```
116 |
117 | ### Instance properties
118 |
119 | ```js
120 | // properties
121 | bits.buffer;
122 | bits.byteLength;
123 | bits.byteOffset;
124 | bits.length;
125 |
126 | ```
127 |
128 | ### static properties
129 |
130 | ```js
131 | BitArray.BYTES_PER_ELEMENT; // 0.125 == 1/8, read-only
132 | BitArray.name; // "BitArray", read-only
133 | BitArray.prototype; // Object {...}
134 | ```
135 |
136 | ## Implementation notes
137 |
138 | For the most part, mapping the behaviour of standard _methods_ and _properties_ to the case of bit arrays is obvious. There are a few caveats though.
139 |
140 | _Note: not all features of the specification are implemented yet **[[WIP](https://github.com/swiing/Bit-TypedArray/issues/3); PRs welcome!]**._
141 |
142 | ### Setting values
143 |
144 | In standard typed arrays, except for the Uint8clamped type, values exceeding the limits go round. For instance, setting value 257 to a Uint8 results in the value of 1 (== 257 % 0xFF). Also, non-numerical values become 0.
145 |
146 | With BitArray, values are first coerced to number. If the result is truthy, the bit will be set to 1; 0 otherwise.
147 |
148 | ```js
149 | let arr = new BitArray(2);
150 |
151 | // one would normally set values like this
152 | arr[0] = 0;
153 | arr[1] = 1;
154 |
155 | // or using booleans:
156 | arr[0] = false;
157 | arr[1] = true;
158 |
159 | // this will also work
160 | arr[0] = -.000001; // arr[0] === 1, because Boolean(-.000001) === true
161 | arr[1] = "a"; // arr[1] === 0, because Number("a") === NaN, which is falsy
162 | ```
163 |
164 | ### `.toString()` method
165 |
166 | The standard method returns a comma-separated list of numbers. In the case of bit sequences, interleaving commas is unnecessarily heavy, for no benefit. Instead, we list 0|1 bits in sequence, grouping them by eight for better clarity (human-reading), and separating groups by a space rather than a comma, to match common practice of text representation of bit sequences.
167 |
168 | ```js
169 | new BitArray(20).toString(); // "00000000 00000000 0000"
170 | ```
171 |
172 | ## License
173 |
174 | [](https://github.com/swiing/Bit-TypedArray/blob/main/LICENSE)
175 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Open the console (ctrl+shift+I)
39 | and reload (F5) to be able to inspect elements in the console.
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/example/index.mjs:
--------------------------------------------------------------------------------
1 | import BitArray from "../dist/esm/bit-typedarray.js";
2 | import { log as _, logHeader as _$ } from "./util.mjs";
3 |
4 | const len = 48; // choose any integer value
5 |
6 | _$("Initializing");
7 |
8 | const randomArray = new BitArray(len);
9 | for( let i=0, bool; i 0.5); // randomly
11 |
12 | _("array is", randomArray);
13 | _("instanceof BitArray ==", randomArray instanceof BitArray);
14 |
15 | _("BitArray.from()", BitArray.from("11001010"));
16 | _("BitArray.of()", BitArray.of(1,1,0,0,1,0,1,0));
17 |
18 |
19 | _$("Iterating");
20 |
21 | let res;
22 |
23 | // following three output the same
24 | res=[];
25 | for( let i=0; i { _("."+prop+":", randomArray[prop] ); });
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/example/util.mjs:
--------------------------------------------------------------------------------
1 | // style for console output formatting
2 | const styleHeader = new Array(200).fill(".").join("") // make sure the formatting text is not visible on the html document
3 | // (it is far to the right, hence overflows)
4 | + "; color:blue; font-weight: bold; font-size: x-large;"
5 |
6 | function logHeader( arg0, ...rest ) {
7 | console.info( "%c> "+arg0, ...rest, styleHeader );
8 | }
9 |
10 | function log() {
11 | console.log(...arguments);
12 | }
13 |
14 | export { log, logHeader }
15 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitarray/typedarray",
3 | "version": "1.1.1",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "@bitarray/typedarray",
9 | "version": "1.1.1",
10 | "license": "MIT",
11 | "devDependencies": {
12 | "prettier": "3.5.3",
13 | "ts-node": "^10.7.0",
14 | "typescript": "^5.0.2"
15 | }
16 | },
17 | "node_modules/@cspotcode/source-map-support": {
18 | "version": "0.8.1",
19 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
20 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
21 | "dev": true,
22 | "dependencies": {
23 | "@jridgewell/trace-mapping": "0.3.9"
24 | },
25 | "engines": {
26 | "node": ">=12"
27 | }
28 | },
29 | "node_modules/@jridgewell/resolve-uri": {
30 | "version": "3.1.0",
31 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
32 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
33 | "dev": true,
34 | "engines": {
35 | "node": ">=6.0.0"
36 | }
37 | },
38 | "node_modules/@jridgewell/sourcemap-codec": {
39 | "version": "1.4.14",
40 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
41 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
42 | "dev": true
43 | },
44 | "node_modules/@jridgewell/trace-mapping": {
45 | "version": "0.3.9",
46 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
47 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
48 | "dev": true,
49 | "dependencies": {
50 | "@jridgewell/resolve-uri": "^3.0.3",
51 | "@jridgewell/sourcemap-codec": "^1.4.10"
52 | }
53 | },
54 | "node_modules/@tsconfig/node10": {
55 | "version": "1.0.9",
56 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
57 | "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
58 | "dev": true
59 | },
60 | "node_modules/@tsconfig/node12": {
61 | "version": "1.0.11",
62 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
63 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
64 | "dev": true
65 | },
66 | "node_modules/@tsconfig/node14": {
67 | "version": "1.0.3",
68 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
69 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
70 | "dev": true
71 | },
72 | "node_modules/@tsconfig/node16": {
73 | "version": "1.0.3",
74 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
75 | "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
76 | "dev": true
77 | },
78 | "node_modules/@types/node": {
79 | "version": "18.19.54",
80 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz",
81 | "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==",
82 | "dev": true,
83 | "license": "MIT",
84 | "peer": true,
85 | "dependencies": {
86 | "undici-types": "~5.26.4"
87 | }
88 | },
89 | "node_modules/acorn": {
90 | "version": "8.8.2",
91 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
92 | "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
93 | "dev": true,
94 | "bin": {
95 | "acorn": "bin/acorn"
96 | },
97 | "engines": {
98 | "node": ">=0.4.0"
99 | }
100 | },
101 | "node_modules/acorn-walk": {
102 | "version": "8.2.0",
103 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
104 | "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
105 | "dev": true,
106 | "engines": {
107 | "node": ">=0.4.0"
108 | }
109 | },
110 | "node_modules/arg": {
111 | "version": "4.1.3",
112 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
113 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
114 | "dev": true
115 | },
116 | "node_modules/create-require": {
117 | "version": "1.1.1",
118 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
119 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
120 | "dev": true
121 | },
122 | "node_modules/diff": {
123 | "version": "4.0.2",
124 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
125 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
126 | "dev": true,
127 | "engines": {
128 | "node": ">=0.3.1"
129 | }
130 | },
131 | "node_modules/make-error": {
132 | "version": "1.3.6",
133 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
134 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
135 | "dev": true
136 | },
137 | "node_modules/prettier": {
138 | "version": "3.5.3",
139 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
140 | "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
141 | "dev": true,
142 | "license": "MIT",
143 | "bin": {
144 | "prettier": "bin/prettier.cjs"
145 | },
146 | "engines": {
147 | "node": ">=14"
148 | },
149 | "funding": {
150 | "url": "https://github.com/prettier/prettier?sponsor=1"
151 | }
152 | },
153 | "node_modules/ts-node": {
154 | "version": "10.9.2",
155 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
156 | "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
157 | "dev": true,
158 | "dependencies": {
159 | "@cspotcode/source-map-support": "^0.8.0",
160 | "@tsconfig/node10": "^1.0.7",
161 | "@tsconfig/node12": "^1.0.7",
162 | "@tsconfig/node14": "^1.0.0",
163 | "@tsconfig/node16": "^1.0.2",
164 | "acorn": "^8.4.1",
165 | "acorn-walk": "^8.1.1",
166 | "arg": "^4.1.0",
167 | "create-require": "^1.1.0",
168 | "diff": "^4.0.1",
169 | "make-error": "^1.1.1",
170 | "v8-compile-cache-lib": "^3.0.1",
171 | "yn": "3.1.1"
172 | },
173 | "bin": {
174 | "ts-node": "dist/bin.js",
175 | "ts-node-cwd": "dist/bin-cwd.js",
176 | "ts-node-esm": "dist/bin-esm.js",
177 | "ts-node-script": "dist/bin-script.js",
178 | "ts-node-transpile-only": "dist/bin-transpile.js",
179 | "ts-script": "dist/bin-script-deprecated.js"
180 | },
181 | "peerDependencies": {
182 | "@swc/core": ">=1.2.50",
183 | "@swc/wasm": ">=1.2.50",
184 | "@types/node": "*",
185 | "typescript": ">=2.7"
186 | },
187 | "peerDependenciesMeta": {
188 | "@swc/core": {
189 | "optional": true
190 | },
191 | "@swc/wasm": {
192 | "optional": true
193 | }
194 | }
195 | },
196 | "node_modules/typescript": {
197 | "version": "5.8.3",
198 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
199 | "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
200 | "dev": true,
201 | "license": "Apache-2.0",
202 | "bin": {
203 | "tsc": "bin/tsc",
204 | "tsserver": "bin/tsserver"
205 | },
206 | "engines": {
207 | "node": ">=14.17"
208 | }
209 | },
210 | "node_modules/undici-types": {
211 | "version": "5.26.5",
212 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
213 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
214 | "dev": true,
215 | "license": "MIT",
216 | "peer": true
217 | },
218 | "node_modules/v8-compile-cache-lib": {
219 | "version": "3.0.1",
220 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
221 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
222 | "dev": true
223 | },
224 | "node_modules/yn": {
225 | "version": "3.1.1",
226 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
227 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
228 | "dev": true,
229 | "engines": {
230 | "node": ">=6"
231 | }
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitarray/typedarray",
3 | "version": "1.1.1",
4 | "description": "A BitArray object exhibiting the interface of standard ecmascript TypedArray's",
5 | "type": "module",
6 | "typings": "./dist/esm/bit-typedarray.d.ts",
7 | "exports": {
8 | ".": {
9 | "types": "./dist/esm/bit-typedarray.d.ts",
10 | "import": "./dist/esm/bit-typedarray.js",
11 | "require": "./dist/cjs/bit-typedarray.js"
12 | }
13 | },
14 | "directories": {
15 | "example": "example",
16 | "test": "test"
17 | },
18 | "scripts": {
19 | "build": "npm run build:cjs && npm run build:esm && npm run build:types",
20 | "build:cjs": "tsc -p tsconfig.cjs.json",
21 | "build:esm": "tsc -p tsconfig.esm.json",
22 | "build:types": "tsc --emitDeclarationOnly -p tsconfig.json",
23 | "example": "NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" node example/index.mjs",
24 | "postbuild": "bash ./scripts/postbuild.sh",
25 | "prepare": "npm run build",
26 | "prepublishOnly": "npm run test",
27 | "style:fix": "prettier src/**/*.ts --write",
28 | "style:check": "prettier src/**/*.ts --check",
29 | "test": "node --test --loader ts-node/esm ./test/index.ts",
30 | "test:ci": "set TS_NODE_PROJECT=./tsconfig.esm.json && node --no-warnings=ExperimentalWarning --loader ts-node/esm ./test/index.ts"
31 | },
32 | "repository": {
33 | "type": "git",
34 | "url": "git+https://github.com/swiing/Bit-TypedArray.git"
35 | },
36 | "keywords": [
37 | "bitarray",
38 | "typedarray"
39 | ],
40 | "author": "swiing",
41 | "license": "MIT",
42 | "bugs": {
43 | "url": "https://github.com/swiing/Bit-TypedArray/issues"
44 | },
45 | "homepage": "https://github.com/swiing/Bit-TypedArray#readme",
46 | "devDependencies": {
47 | "prettier": "3.5.3",
48 | "ts-node": "^10.7.0",
49 | "typescript": "^5.0.2"
50 | },
51 | "files": [
52 | "dist"
53 | ]
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/postbuild.sh:
--------------------------------------------------------------------------------
1 | cat >dist/cjs/package.json <dist/esm/package.json <();
19 |
20 | // // We could make it available to the outside world so it can benefit as well.
21 | // // Should we prefer to keep this private, it would also be possible.
22 | // // In such a case, it would be up to the outside world to manage
23 | // // its own instance of a viewer, e.g. if required for performance reasons.
24 | // export { _views };
25 |
26 | // store ownKeys computation to avoid repeating each time
27 | const _keys = new WeakMap();
28 |
29 | // for my proxy
30 | const handlers = {
31 | get: function (target: BitArray, prop: string | symbol) {
32 | if (typeof prop === 'string') {
33 | const index = Number(prop);
34 | if (index === Math.trunc(index) && index >= 0 && index < target.length) {
35 | const [intIndex, bitMask] = bitIndex2coord(index);
36 | return Number(Boolean(_views.get(target.buffer)[intIndex] & bitMask));
37 | }
38 | }
39 |
40 | return Reflect.get(target, prop);
41 | },
42 |
43 | // In standard typed arrays, except for the Uint8clamped type, values
44 | // exceeding the limits go round. For instance, setting value 257 to
45 | // a Uint8 results in the value 1 (== 257 % 0xFF).
46 | // Here, any value coerced to a boolean that is truthy will result
47 | // in setting value 1; 0 otherwise.
48 | set: function (
49 | target: BitArray,
50 | prop: string | symbol,
51 | value: bit | boolean
52 | ) {
53 | if (typeof prop === 'string') {
54 | const index = Number(prop);
55 | if (index === Math.trunc(index) && index >= 0 && index < target.length) {
56 | const view = _views.get(target.buffer);
57 | const [intIndex, bitMask] = bitIndex2coord(index);
58 | view[intIndex] = Boolean(value)
59 | ? view[intIndex] | bitMask
60 | : view[intIndex] & ~bitMask;
61 | return true;
62 | }
63 | }
64 |
65 | return Reflect.set(target, prop, value);
66 | },
67 |
68 | // We want to be able to use e.g. for( let i in ... )
69 | // so ownKeys must return the indexes
70 | ownKeys: (target: BitArray): string[] => {
71 | let keys: string[] = _keys.get(target);
72 |
73 | if (!keys)
74 | // construct and store keys once for all
75 | _keys.set(
76 | target,
77 | (keys = Array(target.length)
78 | .fill(void 0)
79 | .map((_, i) => i.toString()))
80 | );
81 |
82 | return keys;
83 | },
84 |
85 | // Needed to make ownKeys work as expected.
86 | // see https://javascript.info/proxy#iteration-with-ownkeys-and-getownpropertydescriptor
87 | getOwnPropertyDescriptor: (/*target: BitArray, prop*/): object => ({
88 | enumerable: true,
89 | configurable: true,
90 | }),
91 | };
92 |
93 | class BitArray implements Iterable {
94 | buffer: ArrayBufferLike;
95 | byteLength: number;
96 | byteOffset: number;
97 | length: number;
98 | prototype: object;
99 | [Symbol.iterator]: () => Iterator;
100 | [index: number]: bit;
101 |
102 | static BYTES_PER_ELEMENT = 1 / 8;
103 |
104 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/from
105 | static from(source: Iterable /*, mapFn?, thisArg?*/) {
106 | return new this(source);
107 | }
108 |
109 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/of
110 | static of(...items) {
111 | // let ret = new this( items.length );
112 | // for( let i in items ) ret[i] = Number( (items[i]) );
113 | // return ret;
114 | // simplified into
115 | return this.from(items);
116 | }
117 |
118 | /**
119 | * At this stage, only the ( length ) signature is supported.
120 | * @todo: other signatures - cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
121 | * @param length
122 | * @returns a proxy instance
123 | */
124 | // In order to mimic native TypedArrays, it must be possible to use things
125 | // like myBitArray[i], and for..in loops. The only way to achieve this is
126 | // by using a proxy. The object _itself_ must be a proxy.
127 | // It is NOT possible to extend Proxy's. However, it is possible to return
128 | // a proxy from the constructor.
129 | constructor(arg: number /*| TypedArray @todo */ | Iterable) {
130 | let byteOffset = 0;
131 | let byteLength: number;
132 | let buffer: ArrayBufferLike;
133 | let length = 0;
134 |
135 | const argIsIterable = Symbol.iterator in Object(arg);
136 |
137 | if (argIsIterable) for (let _ of arg as Iterable) length++;
138 | else {
139 | length = Math.trunc(arg as number);
140 |
141 | if (length < 0) throw new RangeError('invalid array length');
142 | }
143 |
144 | byteLength = (((length - 1) >> 5) + 1) * 4;
145 | buffer = new ArrayBuffer(byteLength);
146 |
147 | // by default, properties are not writable, which is what I need
148 | // however, I need to have them configurable, as per https://stackoverflow.com/a/42876020
149 | Object.defineProperties(this, {
150 | byteOffset: { value: byteOffset, configurable: true },
151 | byteLength: { value: byteLength, configurable: true },
152 | buffer: { value: buffer, configurable: true },
153 | length: { value: length, configurable: true },
154 | });
155 |
156 | // store once for all a viewer for this buffer (see above)
157 | //
158 | // Note 1: we can NOT use 'this' as the key for the weakmap, because
159 | // here 'this' refers to the target, while later on, 'this' will refer
160 | // to the proxy (because of the return statement in this constructor
161 | // - see below). Or else, we would need to derive the proxy from the
162 | // target (does not look very nice).
163 | //
164 | // Note 2: this implies, if two instances of BitArray's share the same
165 | // buffer, they will also share the same viewer. It is not a problem
166 | // unless maybe one of the bit arrays is constructed with an offset.
167 | // I have not thought too much about it yet: it seems a very corner
168 | // case when it comes to usage of bit arrays; and such construction
169 | // is not supported at this stage anyway.
170 | _views.set(this.buffer, new Uint32Array(this.buffer));
171 |
172 | let ret = Reflect.construct(Proxy, [this, handlers]);
173 |
174 | if (argIsIterable)
175 | // beware Boolean("0") === true, so make sure to convert to number first;
176 | for (let i in arg as Iterable) ret[i] = Number(arg[i]);
177 |
178 | return ret;
179 | }
180 |
181 | /**
182 | * Returns a string representation of an array.
183 | */
184 | // standard TypeArray's return comma-separated values. Here, we deliberately
185 | // choose not to include commas as it makes the string very heavy-weight,
186 | // for no benefit.
187 | toString() {
188 | // Object.values is an es2017 feature => avoid to remain ES6 compliant
189 | // return Object.values(this)
190 | // .map( String )
191 | // // add one space between each byte - it could be argued
192 | // // if this is the right thing to do. I think it replaces
193 | // // nicely the comma in the native TypedArry's toString()
194 | // // since here we are looking at bits.
195 | // // Most obvious alternative would probably be to remove
196 | // // completely this line. It is hard to read for a human,
197 | // // though.
198 | // .map( (b:"0"|"1", i:number) => (i+1)%8 ? b : b+" " )
199 | // .join("")
200 | // .trim();
201 | var ret = '';
202 | for (let i = 0; i < this.length; i++)
203 | ret += String(this[i]) + ((i + 1) % 8 ? '' : ' ');
204 |
205 | // trimEnd() would be suitable but is an es2019 feature,
206 | // while we want to remain ES6-compatible.
207 | return ret.trim();
208 | }
209 |
210 | /**
211 | * Performs the specified action for each element in an array.
212 | * @param callbackfn A function that accepts up to three arguments. forEach calls the
213 | * callbackfn function one time for each element in the array.
214 | * @param thisArg An object to which the this keyword can refer in the callbackfn function.
215 | * If thisArg is omitted, undefined is used as the this value.
216 | */
217 | forEach(
218 | callbackfn: (value: bit, index: number, array: BitArray) => void,
219 | thisArg?: any
220 | ): void {
221 | if (typeof callbackfn !== 'function')
222 | throw new TypeError(callbackfn + ' is not a function');
223 |
224 | thisArg = thisArg || undefined;
225 | for (let i = 0; i < this.length; i++)
226 | callbackfn.call(thisArg, this[i], i, this);
227 | }
228 |
229 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/at
230 | //
231 | // Note: this is an experimental feature.
232 | //
233 | // Inspired by https://github.com/tc39/proposal-relative-indexing-method#polyfill
234 | at(index: number): bit | undefined {
235 | index = Math.trunc(index) || 0;
236 |
237 | // If a negative number is used, the element returned
238 | // will be found by counting back from the end of the array.
239 | if (index < 0) index += this.length;
240 |
241 | // out-of-bounds access is guaranteed to return undefined
242 | if (index < 0 || index >= this.length) return void 0;
243 |
244 | // const [intIndex, bitMask] = bitIndex2coord( index );
245 | // return Number( _views.get( this.buffer )[ intIndex ] & bitMask );
246 | // the above can be simplified as follows
247 | // (avoids duplication of code, though less performant)
248 | return this[index];
249 | }
250 |
251 | /**
252 | * Sets a value or an array of values.
253 | * @param array A typed or untyped array of values to set.
254 | * @param offset The index in the current array at which the values are to be written.
255 | */
256 | // cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set
257 | //
258 | // Should we enforce value to be a number, or allow anything,
259 | // that would coerce to a number inside the method?
260 | //
261 | // Should we keep allowing an offset? Obviously, this is according to
262 | // the native TypedArray's, but can it have any use for BitArrays?
263 | set(array: ArrayLike | ArrayLike, offset: number = 0) {
264 | if (offset < 0 || offset >= this.length)
265 | throw new RangeError('invalid or out-of-range index');
266 |
267 | if (offset + array.length > this.length)
268 | throw new RangeError('source array is too long');
269 |
270 | // const view = _views.get( this.buffer );
271 |
272 | for (let i = 0; i < array.length; i++) {
273 | // const [intIndex, bitMask] = bitIndex2coord( offset+i );
274 | // view[ intIndex ] = array[i] ? view[ intIndex ] | bitMask
275 | // : view[ intIndex ] & ~bitMask;
276 | // the above can be simplified as follows
277 | // (avoids duplication of code, though less performant)
278 | //
279 | // @ts-ignore (the proxy handler will manage the case array[i] is a boolean)
280 | this[offset + i] = array[i];
281 | }
282 | }
283 |
284 | values() {
285 | let currentIndex = 0;
286 | return {
287 | next: () => {
288 | return currentIndex < this.length
289 | ? { done: false, value: this[currentIndex++] }
290 | : ({ done: true } as IteratorResult);
291 | },
292 | };
293 | }
294 | }
295 |
296 | // utility function
297 | /**
298 | *
299 | * @param index
300 | * @returns the Uint32 index and bit mask that can be used by a Uint32 viewer
301 | * to access the index'th value of the bit array.
302 | */
303 | function bitIndex2coord(index: number): [number, number] {
304 | return [
305 | index >> 5, // divide by 32
306 | 1 << (index & 31), // modulo 32
307 | ];
308 | }
309 |
310 | // as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/values
311 | // "Array.prototype.values is default implementation of Array.prototype[Symbol.iterator]"
312 | BitArray.prototype[Symbol.iterator] = BitArray.prototype.values;
313 |
314 | // according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#description
315 | // "ECMAScript 2015 defines a TypedArray constructor that serves as the [[Prototype]]
316 | // of all TypedArray constructors. This constructor is not directly exposed:
317 | // there is no global %TypedArray% or TypedArray property. It is only directly accessible
318 | // through Object.getPrototypeOf(Int8Array) and similar. All TypedArrays constructors
319 | // inherit common properties from the %TypedArray% constructor function. Additionally,
320 | // all typed array prototypes (TypedArray.prototype) have %TypedArray%.prototype as their
321 | // [[Prototype]]."
322 | //
323 | // In practice, it is not very useful because implementation detects BitArray is not
324 | // a true (native) typed array, and trying to call methods on the TypedArray prototype
325 | // throws, e.g. TypeError: CallTypedArrayMethodIfWrapped method called on incompatible Proxy.
326 | // Object.setPrototypeOf( BitArray.prototype , Object.getPrototypeOf(Int8Array).prototype );
327 |
328 | export default BitArray;
329 | export { bit };
330 |
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | import suite from './suite.js';
2 | import test from './test.js';
3 |
4 | test(suite);
5 |
--------------------------------------------------------------------------------
/test/suite.ts:
--------------------------------------------------------------------------------
1 | import BitArray from '../src/bit-typedarray.js';
2 |
3 | // whatever value >=4
4 | // Some test cases are not accounting for a zero length (and would appear as failures)
5 | // (but, in general, it is obviously allowed to have a zero-size bit array)
6 | const length = 48;
7 |
8 | const bits = new BitArray(length);
9 |
10 | /** suite 1 */
11 | const instantiating = {
12 | 'new BitArray( length )': bits instanceof BitArray,
13 | 'length is set': bits.length === length,
14 | 'empty bit array has length 0': new BitArray(0).length === 0,
15 | 'new BitArray( iterable )':
16 | new BitArray('011010') instanceof BitArray &&
17 | new BitArray('011010').length === 6,
18 | };
19 |
20 | /** suite 2 */
21 | const reading_writing = {
22 | 'default value set to 0': bits[0] === 0 && bits[length - 1] === 0,
23 | 'bits[n] = true sets bit value to 1':
24 | // @ts-ignore true type as bit
25 | ((bits[length - 1] = true), bits[length - 1] === 1),
26 | 'bits[n] = 1 sets bit value to 1':
27 | ((bits[length - 1] = 1), bits[length - 1] === 1),
28 | '.at(n)': bits.at(length - 1) === 1,
29 | // this test assumes a minimal length, otherwise we don't run and simply return "pass ok".
30 | '.set([true,false], 2)':
31 | length < 4
32 | ? true
33 | : (bits.set([true, false], 2), bits[2] === 1 && bits[3] === 0),
34 | '.set([1,1], 2)':
35 | length < 4 ? true : (bits.set([1, 1], 2), bits[2] === 1 && bits[3] === 1),
36 | };
37 |
38 | /** suite 3 */
39 | // we check only that the last value is as expected,
40 | // and assume this is enough evidence to consider the loop was okay
41 | const iterating = {
42 | 'for loop': (() => {
43 | let item, index;
44 | for (let i = 0; i < length; i++) item = bits[(index = i)];
45 | return index === length - 1 && item === 1;
46 | })(),
47 |
48 | 'for..in loop': (() => {
49 | let item, index;
50 | for (let i in bits) item = bits[(index = i)];
51 | return index === '' + (length - 1) && item === 1;
52 | })(),
53 |
54 | '.forEach()': (() => {
55 | let res, index;
56 | bits.forEach((val, i, arr) => {
57 | index = i;
58 | res = arr[i] === val;
59 | });
60 | return index === length - 1 && res === true;
61 | })(),
62 |
63 | 'for..of loop': (() => {
64 | let item,
65 | index = 0;
66 | for (item of bits) index++;
67 | return item === 1 && index === length;
68 | })(),
69 | };
70 |
71 | /** suite 4 */
72 | const formatting = {
73 | '.toString()':
74 | bits.toString() ===
75 | new Array(length)
76 | .fill(0)
77 | .map((c, i) => ((i + 1) % 8 ? c : c + ' '))
78 | .join('')
79 | .trim()
80 | // bits 2 and 3 have been set to 1 in my test cases
81 | .replace(/0000/, '0011')
82 | // last bit have been set to 1 in my test cases
83 | .replace(/.$/, '1'),
84 | };
85 |
86 | /** suite 5 */
87 | const static_metods = {
88 | 'BitArray.from( boolean[] )': (() => {
89 | let arr = BitArray.from([true, true, false, false, true]);
90 | return (
91 | arr instanceof BitArray &&
92 | arr.length === 5 &&
93 | arr[0] === 1 &&
94 | arr[1] === 1 &&
95 | arr[2] === 0 &&
96 | arr[3] === 0 &&
97 | arr[4] === 1
98 | );
99 | })(),
100 |
101 | 'BitArray.from( number[] )': (() => {
102 | let arr = BitArray.from([1, 1, 0, 0, 1]);
103 | return (
104 | arr instanceof BitArray &&
105 | arr.length === 5 &&
106 | arr[0] === 1 &&
107 | arr[1] === 1 &&
108 | arr[2] === 0 &&
109 | arr[3] === 0 &&
110 | arr[4] === 1
111 | );
112 | })(),
113 |
114 | 'BitArray.from( string )': (() => {
115 | let arr = BitArray.from('11001');
116 | return (
117 | arr instanceof BitArray &&
118 | arr.length === 5 &&
119 | arr[0] === 1 &&
120 | arr[1] === 1 &&
121 | arr[2] === 0 &&
122 | arr[3] === 0 &&
123 | arr[4] === 1
124 | );
125 | })(),
126 |
127 | 'BitArray.of( ...booleans )': (() => {
128 | let arr = BitArray.of(true, true, false, false, true);
129 | return (
130 | arr instanceof BitArray &&
131 | arr.length === 5 &&
132 | arr[0] === 1 &&
133 | arr[1] === 1 &&
134 | arr[2] === 0 &&
135 | arr[3] === 0 &&
136 | arr[4] === 1
137 | );
138 | })(),
139 |
140 | 'BitArray.of( ...numbers )': (() => {
141 | let arr = BitArray.of(1, 1, 0, 0, 1);
142 | return (
143 | arr instanceof BitArray &&
144 | arr.length === 5 &&
145 | arr[0] === 1 &&
146 | arr[1] === 1 &&
147 | arr[2] === 0 &&
148 | arr[3] === 0 &&
149 | arr[4] === 1
150 | );
151 | })(),
152 | };
153 |
154 | export default {
155 | instantiating,
156 | reading_writing,
157 | iterating,
158 | formatting,
159 | static_metods,
160 | };
161 |
--------------------------------------------------------------------------------
/test/test.ts:
--------------------------------------------------------------------------------
1 | // coloring in node
2 | const
3 | NodeFailure = "\x1b[31m", // red
4 | NodeSuccess = "\x1b[32m", // green
5 | NodeInfo = "\x1b[37m"; // white
6 |
7 | // coloring in browser
8 | const
9 | BrowserFailure = "color:red;",
10 | BrowserSuccess = "color:green;",
11 | BrowserInfo = "color:darkgrey;font-size: x-large;";
12 |
13 | const log = typeof window === "object"
14 | ? // in browser
15 | function( success: boolean|undefined, text: string, tab: string ) {
16 | success == true ? console.log( "%c" + tab + text, BrowserSuccess )
17 | : success == false ? console.log( "%c" + tab + text, BrowserFailure )
18 | : console.log( "%c" + tab + text, BrowserInfo );
19 | }
20 | : // in node
21 | function( success: boolean|undefined, text: string, tab: string ) {
22 | success == true ? console.log( NodeSuccess + tab + text + NodeInfo )
23 | : success == false ? console.log( NodeFailure + tab + text + NodeInfo )
24 | : console.log( tab + text );
25 | };
26 |
27 |
28 | export default function test( suite: object, tab="" ) {
29 |
30 | let success: boolean;
31 |
32 | // for( let [desc, success] of Object.entries( suite ) ) // es2017
33 | for( let desc of Object.keys( suite ) ) {
34 | success = suite[desc];
35 |
36 | if( typeof success === "boolean" )
37 | log( success, desc, tab );
38 | else {
39 | log( undefined, desc, tab );
40 | test( success, tab+"\t" );
41 | }
42 |
43 | }
44 |
45 | };
46 |
--------------------------------------------------------------------------------
/tsconfig.cjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "outDir": "dist/cjs/"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.esm.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "es6",
5 | "target": "es6",
6 | "outDir": "dist/esm/",
7 | "esModuleInterop": true,
8 | "moduleResolution": "node"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "moduleResolution": "node",
5 | "declarationDir": "./dist/esm",
6 | "declaration": true,
7 | "module": "es6",
8 | "outDir": "dist/esm/",
9 | "esModuleInterop": true
10 | },
11 | "ts-node": { "esm": true },
12 | "files": ["src/bit-typedarray.ts"]
13 | }
14 |
--------------------------------------------------------------------------------