@sapphire/bitfield 1.0.0 β 1.0.1-next.009d3d2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -68
- package/dist/index.d.ts +4 -4
- package/dist/index.global.js +145 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +145 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +145 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -236,71 +236,14 @@ We accept donations through Open Collective, Ko-fi, PayPal, Patreon and GitHub S
|
|
|
236
236
|
| Patreon | [Click Here](https://sapphirejs.dev/patreon) |
|
|
237
237
|
| PayPal | [Click Here](https://sapphirejs.dev/paypal) |
|
|
238
238
|
|
|
239
|
-
## Contributors
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
<td align="center"><a href="https://github.com/PyroTechniac"><img src="https://avatars2.githubusercontent.com/u/39341355?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gryffon Bellish</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=PyroTechniac" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/pulls?q=is%3Apr+reviewed-by%3APyroTechniac" title="Reviewed Pull Requests">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=PyroTechniac" title="Tests">β οΈ</a></td>
|
|
251
|
-
<td align="center"><a href="https://github.com/vladfrangu"><img src="https://avatars3.githubusercontent.com/u/17960496?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vlad Frangu</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=vladfrangu" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/issues?q=author%3Avladfrangu" title="Bug reports">π</a> <a href="https://github.com/sapphiredev/utilities/pulls?q=is%3Apr+reviewed-by%3Avladfrangu" title="Reviewed Pull Requests">π</a> <a href="#userTesting-vladfrangu" title="User Testing">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=vladfrangu" title="Tests">β οΈ</a></td>
|
|
252
|
-
<td align="center"><a href="https://github.com/Stitch07"><img src="https://avatars0.githubusercontent.com/u/29275227?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stitch07</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Stitch07" title="Code">π»</a> <a href="#projectManagement-Stitch07" title="Project Management">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=Stitch07" title="Tests">β οΈ</a></td>
|
|
253
|
-
<td align="center"><a href="https://github.com/apps/depfu"><img src="https://avatars3.githubusercontent.com/in/715?v=4?s=100" width="100px;" alt=""/><br /><sub><b>depfu[bot]</b></sub></a><br /><a href="#maintenance-depfu[bot]" title="Maintenance">π§</a></td>
|
|
254
|
-
<td align="center"><a href="https://github.com/apps/allcontributors"><img src="https://avatars0.githubusercontent.com/in/23186?v=4?s=100" width="100px;" alt=""/><br /><sub><b>allcontributors[bot]</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=allcontributors[bot]" title="Documentation">π</a></td>
|
|
255
|
-
</tr>
|
|
256
|
-
<tr>
|
|
257
|
-
<td align="center"><a href="https://github.com/Nytelife26"><img src="https://avatars1.githubusercontent.com/u/22531310?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tyler J Russell</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Nytelife26" title="Documentation">π</a></td>
|
|
258
|
-
<td align="center"><a href="https://github.com/Alcremie"><img src="https://avatars0.githubusercontent.com/u/54785334?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ivan Lieder</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Alcremie" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/issues?q=author%3AAlcremie" title="Bug reports">π</a></td>
|
|
259
|
-
<td align="center"><a href="https://github.com/RealShadowNova"><img src="https://avatars3.githubusercontent.com/u/46537907?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hezekiah Hendry</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=RealShadowNova" title="Code">π»</a> <a href="#tool-RealShadowNova" title="Tools">π§</a></td>
|
|
260
|
-
<td align="center"><a href="https://github.com/Vetlix"><img src="https://avatars.githubusercontent.com/u/31412314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vetlix</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Vetlix" title="Code">π»</a></td>
|
|
261
|
-
<td align="center"><a href="https://github.com/ethamitc"><img src="https://avatars.githubusercontent.com/u/27776796?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ethan Mitchell</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=ethamitc" title="Documentation">π</a></td>
|
|
262
|
-
<td align="center"><a href="https://github.com/noftaly"><img src="https://avatars.githubusercontent.com/u/34779161?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Elliot</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=noftaly" title="Code">π»</a></td>
|
|
263
|
-
<td align="center"><a href="https://jurien.dev"><img src="https://avatars.githubusercontent.com/u/5418114?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jurien Hamaker</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=jurienhamaker" title="Code">π»</a></td>
|
|
264
|
-
</tr>
|
|
265
|
-
<tr>
|
|
266
|
-
<td align="center"><a href="https://fanoulis.dev/"><img src="https://avatars.githubusercontent.com/u/38255093?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Charalampos Fanoulis</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=cfanoulis" title="Documentation">π</a></td>
|
|
267
|
-
<td align="center"><a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dependabot[bot]</b></sub></a><br /><a href="#maintenance-dependabot[bot]" title="Maintenance">π§</a></td>
|
|
268
|
-
<td align="center"><a href="https://kaname.netlify.app/"><img src="https://avatars.githubusercontent.com/u/56084970?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kaname</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=kaname-png" title="Code">π»</a></td>
|
|
269
|
-
<td align="center"><a href="https://github.com/nandhagk"><img src="https://avatars.githubusercontent.com/u/62976649?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nandhagk</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/issues?q=author%3Anandhagk" title="Bug reports">π</a></td>
|
|
270
|
-
<td align="center"><a href="https://megatank58.me/"><img src="https://avatars.githubusercontent.com/u/51410502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>megatank58</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=megatank58" title="Code">π»</a></td>
|
|
271
|
-
<td align="center"><a href="https://github.com/UndiedGamer"><img src="https://avatars.githubusercontent.com/u/84702365?v=4?s=100" width="100px;" alt=""/><br /><sub><b>UndiedGamer</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=UndiedGamer" title="Code">π»</a></td>
|
|
272
|
-
<td align="center"><a href="https://github.com/Lioness100"><img src="https://avatars.githubusercontent.com/u/65814829?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lioness100</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Lioness100" title="Documentation">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=Lioness100" title="Code">π»</a></td>
|
|
273
|
-
</tr>
|
|
274
|
-
<tr>
|
|
275
|
-
<td align="center"><a href="https://gitlab.com/DavidPH/"><img src="https://avatars.githubusercontent.com/u/44669930?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=DavidPHH" title="Code">π»</a></td>
|
|
276
|
-
<td align="center"><a href="https://github.com/apps/renovate"><img src="https://avatars.githubusercontent.com/in/2740?v=4?s=100" width="100px;" alt=""/><br /><sub><b>renovate[bot]</b></sub></a><br /><a href="#maintenance-renovate[bot]" title="Maintenance">π§</a></td>
|
|
277
|
-
<td align="center"><a href="https://renovate.whitesourcesoftware.com/"><img src="https://avatars.githubusercontent.com/u/25180681?v=4?s=100" width="100px;" alt=""/><br /><sub><b>WhiteSource Renovate</b></sub></a><br /><a href="#maintenance-renovate-bot" title="Maintenance">π§</a></td>
|
|
278
|
-
<td align="center"><a href="https://fc5570.me/"><img src="https://avatars.githubusercontent.com/u/68158483?v=4?s=100" width="100px;" alt=""/><br /><sub><b>FC</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=FC5570" title="Code">π»</a></td>
|
|
279
|
-
<td align="center"><a href="https://github.com/Tokipudi"><img src="https://avatars.githubusercontent.com/u/29551076?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JΓ©rΓ©my de Saint Denis</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Tokipudi" title="Code">π»</a></td>
|
|
280
|
-
<td align="center"><a href="https://github.com/ItsMrCube"><img src="https://avatars.githubusercontent.com/u/25201357?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MrCube</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=ItsMrCube" title="Code">π»</a></td>
|
|
281
|
-
<td align="center"><a href="https://github.com/bitomic"><img src="https://avatars.githubusercontent.com/u/35199700?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bitomic</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=bitomic" title="Code">π»</a></td>
|
|
282
|
-
</tr>
|
|
283
|
-
<tr>
|
|
284
|
-
<td align="center"><a href="https://c43721.dev/"><img src="https://avatars.githubusercontent.com/u/55610086?v=4?s=100" width="100px;" alt=""/><br /><sub><b>c43721</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=c43721" title="Code">π»</a></td>
|
|
285
|
-
<td align="center"><a href="https://commandtechno.com/"><img src="https://avatars.githubusercontent.com/u/68407783?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Commandtechno</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Commandtechno" title="Code">π»</a></td>
|
|
286
|
-
<td align="center"><a href="https://github.com/dhruv-kaushikk"><img src="https://avatars.githubusercontent.com/u/73697546?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aura</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=dhruv-kaushikk" title="Code">π»</a></td>
|
|
287
|
-
<td align="center"><a href="https://axis.moe/"><img src="https://avatars.githubusercontent.com/u/54381371?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=axisiscool" title="Code">π»</a></td>
|
|
288
|
-
<td align="center"><a href="https://github.com/imranbarbhuiya"><img src="https://avatars.githubusercontent.com/u/74945038?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Parbez</b></sub></a><br /><a href="#maintenance-imranbarbhuiya" title="Maintenance">π§</a></td>
|
|
289
|
-
<td align="center"><a href="https://github.com/NotKaskus"><img src="https://avatars.githubusercontent.com/u/75168528?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul Andrew</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=NotKaskus" title="Documentation">π</a></td>
|
|
290
|
-
<td align="center"><a href="https://linktr.ee/mzato0001"><img src="https://avatars.githubusercontent.com/u/62367547?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mzato</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Mzato0001" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/issues?q=author%3AMzato0001" title="Bug reports">π</a></td>
|
|
291
|
-
</tr>
|
|
292
|
-
<tr>
|
|
293
|
-
<td align="center"><a href="https://github.com/MajesticString"><img src="https://avatars.githubusercontent.com/u/66224939?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Harry Allen</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=MajesticString" title="Documentation">π</a></td>
|
|
294
|
-
<td align="center"><a href="https://github.com/EvolutionX-10"><img src="https://avatars.githubusercontent.com/u/85353424?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Evo</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=EvolutionX-10" title="Code">π»</a></td>
|
|
295
|
-
<td align="center"><a href="https://enes.ovh/"><img src="https://avatars.githubusercontent.com/u/61084101?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Enes GenΓ§</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=enxg" title="Code">π»</a></td>
|
|
296
|
-
<td align="center"><a href="https://github.com/muchnameless"><img src="https://avatars.githubusercontent.com/u/12682826?v=4?s=100" width="100px;" alt=""/><br /><sub><b>muchnameless</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=muchnameless" title="Code">π»</a></td>
|
|
297
|
-
<td align="center"><a href="https://github.com/r-priyam"><img src="https://avatars.githubusercontent.com/u/50884372?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Priyam</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=r-priyam" title="Code">π»</a></td>
|
|
298
|
-
</tr>
|
|
299
|
-
</table>
|
|
300
|
-
|
|
301
|
-
<!-- markdownlint-restore -->
|
|
302
|
-
<!-- prettier-ignore-end -->
|
|
303
|
-
|
|
304
|
-
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
305
|
-
|
|
306
|
-
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
|
239
|
+
## Contributors
|
|
240
|
+
|
|
241
|
+
Please make sure to read the [Contributing Guide][contributing] before making a pull request.
|
|
242
|
+
|
|
243
|
+
Thank you to all the people who already contributed to Sapphire!
|
|
244
|
+
|
|
245
|
+
<a href="https://github.com/sapphiredev/utilities/graphs/contributors">
|
|
246
|
+
<img src="https://contrib.rocks/image?repo=sapphiredev/utilities" />
|
|
247
|
+
</a>
|
|
248
|
+
|
|
249
|
+
[contributing]: https://github.com/sapphiredev/.github/blob/main/.github/CONTRIBUTING.md
|
package/dist/index.d.ts
CHANGED
|
@@ -159,17 +159,17 @@ declare class BitField<Flags extends Record<string, number> | Record<string, big
|
|
|
159
159
|
*/
|
|
160
160
|
toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean>;
|
|
161
161
|
}
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
type PrimitiveType<T> = T extends number ? number : bigint;
|
|
163
|
+
type MaybeArray<T> = T | readonly T[];
|
|
164
164
|
/**
|
|
165
165
|
* Resolves the type of the values the specified {@link BitField} takes.
|
|
166
166
|
* @typeparam A {@link BitField} instance type.
|
|
167
167
|
*/
|
|
168
|
-
|
|
168
|
+
type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;
|
|
169
169
|
/**
|
|
170
170
|
* Resolves the possible types accepted by the specified {@link BitField}.
|
|
171
171
|
* @typeparam A {@link BitField} instance type.
|
|
172
172
|
*/
|
|
173
|
-
|
|
173
|
+
type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;
|
|
174
174
|
|
|
175
175
|
export { BitField, ValueResolvable, ValueType };
|
package/dist/index.global.js
CHANGED
|
@@ -55,6 +55,15 @@ var SapphireBitField = (function (exports) {
|
|
|
55
55
|
this.mask = mask;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolves a:
|
|
60
|
+
* - `string`: If it's a property of {@link Flags}.
|
|
61
|
+
* - `number`: If the BitField processes `number` primitives.
|
|
62
|
+
* - `bigint`: If the BitField processes `bigint` primitives.
|
|
63
|
+
* - `Array`: Resolves recursively.
|
|
64
|
+
* @param resolvable The value to resolve.
|
|
65
|
+
* @returns The resolved value.
|
|
66
|
+
*/
|
|
58
67
|
resolve(resolvable) {
|
|
59
68
|
switch (typeof resolvable) {
|
|
60
69
|
case "string":
|
|
@@ -71,16 +80,60 @@ var SapphireBitField = (function (exports) {
|
|
|
71
80
|
throw new TypeError(`Received a value that is not either type "string", type "${this.type}", or an Array`);
|
|
72
81
|
}
|
|
73
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Checks whether or not `field` contains any of the bits from `bits`.
|
|
85
|
+
* @param field The bits to compare the bits from.
|
|
86
|
+
* @param bits The bits to compare with.
|
|
87
|
+
* @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.
|
|
88
|
+
*/
|
|
74
89
|
any(field, bits) {
|
|
75
90
|
return (this.resolve(field) & this.resolve(bits)) !== this.zero;
|
|
76
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Checks whether or not `field` is a superset of or equal to `bits`.
|
|
94
|
+
* @param field The bits to compare the bits from.
|
|
95
|
+
* @param bits The bits to compare with.
|
|
96
|
+
* @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.
|
|
97
|
+
*/
|
|
77
98
|
has(field, bits) {
|
|
78
99
|
const resolved = this.resolve(bits);
|
|
79
100
|
return (this.resolve(field) & resolved) === resolved;
|
|
80
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)
|
|
104
|
+
* that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.
|
|
105
|
+
* @param field The bits to get the complement of.
|
|
106
|
+
* @returns The complement of `field`, also denoted `AαΆ` or `A'`.
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const bitfield = new BitField({
|
|
110
|
+
* Read: 0b0001,
|
|
111
|
+
* Write: 0b0010,
|
|
112
|
+
* Edit: 0b0100,
|
|
113
|
+
* Delete: 0b1000
|
|
114
|
+
* });
|
|
115
|
+
*
|
|
116
|
+
* bitfield.complement(0b0100);
|
|
117
|
+
* // 0b1011
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
81
120
|
complement(field) {
|
|
82
121
|
return this.difference(this.mask, field);
|
|
83
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Makes a union of all the bits.
|
|
125
|
+
* @param fields The bits to create a union of.
|
|
126
|
+
* @returns The result of combining all bits together, also denoted as `β
β fields`.
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* bitfield.union(0b0001, 0b0100);
|
|
130
|
+
* // 0b0101
|
|
131
|
+
*
|
|
132
|
+
* bitfield.union(0b1100, 0b0001, 0b0010);
|
|
133
|
+
* // 0b1111
|
|
134
|
+
* ```
|
|
135
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}
|
|
136
|
+
*/
|
|
84
137
|
union(...fields) {
|
|
85
138
|
let field = this.zero;
|
|
86
139
|
for (const resolvable of fields) {
|
|
@@ -88,6 +141,24 @@ var SapphireBitField = (function (exports) {
|
|
|
88
141
|
}
|
|
89
142
|
return field;
|
|
90
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Makes an intersection of all the bits.
|
|
146
|
+
* @param bitfield The first field.
|
|
147
|
+
* @param fields The bits to intersect with `bitfield`.
|
|
148
|
+
* @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* bitfield.intersection(0b0001, 0b0100);
|
|
152
|
+
* // 0b0000
|
|
153
|
+
*
|
|
154
|
+
* bitfield.intersection(0b1100, 0b0100);
|
|
155
|
+
* // 0b0100
|
|
156
|
+
*
|
|
157
|
+
* bitfield.intersection(0b1101, 0b0101, 0b1100);
|
|
158
|
+
* // 0b0100
|
|
159
|
+
* ```
|
|
160
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}
|
|
161
|
+
*/
|
|
91
162
|
intersection(bitfield, ...fields) {
|
|
92
163
|
let field = this.resolve(bitfield);
|
|
93
164
|
for (const resolvable of fields) {
|
|
@@ -95,12 +166,62 @@ var SapphireBitField = (function (exports) {
|
|
|
95
166
|
}
|
|
96
167
|
return field;
|
|
97
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Removes from `a` the bits that exist in `b`.
|
|
171
|
+
* @param a The first field.
|
|
172
|
+
* @param b The bits to remove from `a`.
|
|
173
|
+
* @returns The result of `a β b`.
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* bitfield.difference(0b1100, 0b0100);
|
|
177
|
+
* // 0b1000
|
|
178
|
+
*
|
|
179
|
+
* bitfield.difference(0b1111, 0b0110);
|
|
180
|
+
* // 0b1001
|
|
181
|
+
* ```
|
|
182
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}
|
|
183
|
+
*/
|
|
98
184
|
difference(a, b) {
|
|
99
185
|
return this.resolve(a) & ~this.resolve(b);
|
|
100
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of
|
|
189
|
+
* elements which are in either of the sets, but not in their intersection. As such, this is the result of
|
|
190
|
+
* `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.
|
|
191
|
+
* @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`
|
|
192
|
+
* @param a The first field.
|
|
193
|
+
* @param b The second field.
|
|
194
|
+
* @returns The result of computing `a Ξ b`.
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* bitfield.symmetricDifference(0b1100, 0b0011);
|
|
198
|
+
* // 0b1111
|
|
199
|
+
*
|
|
200
|
+
* bitfield.symmetricDifference(0b1101, 0b1011);
|
|
201
|
+
* // 0b0110
|
|
202
|
+
* ```
|
|
203
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}
|
|
204
|
+
*/
|
|
101
205
|
symmetricDifference(a, b) {
|
|
102
206
|
return this.resolve(a) ^ this.resolve(b);
|
|
103
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.
|
|
210
|
+
* @param field The field to convert to an array.
|
|
211
|
+
* @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.
|
|
212
|
+
* @example
|
|
213
|
+
* ```typescript
|
|
214
|
+
* const bitfield = new BitField({
|
|
215
|
+
* Read: 0b0001,
|
|
216
|
+
* Write: 0b0010,
|
|
217
|
+
* Edit: 0b0100,
|
|
218
|
+
* Delete: 0b1000
|
|
219
|
+
* });
|
|
220
|
+
*
|
|
221
|
+
* bitfield.toArray(0b0101);
|
|
222
|
+
* // ['Read', 'Edit']
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
104
225
|
toArray(field) {
|
|
105
226
|
const bits = this.resolve(field);
|
|
106
227
|
const keys = [];
|
|
@@ -110,6 +231,29 @@ var SapphireBitField = (function (exports) {
|
|
|
110
231
|
}
|
|
111
232
|
return keys;
|
|
112
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the
|
|
236
|
+
* flag's bit is contained in `field`.
|
|
237
|
+
* @param field The field to convert to an object.
|
|
238
|
+
* @returns An object with the properties of {@link Flags} which values are boolean.
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const bitfield = new BitField({
|
|
242
|
+
* Read: 0b0001,
|
|
243
|
+
* Write: 0b0010,
|
|
244
|
+
* Edit: 0b0100,
|
|
245
|
+
* Delete: 0b1000
|
|
246
|
+
* });
|
|
247
|
+
*
|
|
248
|
+
* bitfield.toObject(0b0101);
|
|
249
|
+
* // {
|
|
250
|
+
* // Read: true,
|
|
251
|
+
* // Write: false,
|
|
252
|
+
* // Edit: true,
|
|
253
|
+
* // Delete: false
|
|
254
|
+
* // }
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
113
257
|
toObject(field) {
|
|
114
258
|
const bits = this.resolve(field);
|
|
115
259
|
return Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit]));
|
|
@@ -119,9 +263,8 @@ var SapphireBitField = (function (exports) {
|
|
|
119
263
|
|
|
120
264
|
exports.BitField = BitField;
|
|
121
265
|
|
|
122
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
123
|
-
|
|
124
266
|
return exports;
|
|
125
267
|
|
|
126
268
|
})({});
|
|
269
|
+
//# sourceMappingURL=out.js.map
|
|
127
270
|
//# sourceMappingURL=index.global.js.map
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/BitField.ts"],"names":[],"mappings":";;;;;;;;;AAAO,IAAM,WAAN,MAA8E;AAAA,EAM7E,YAAY,OAAwB;AAL3C,wBAAgB;AAChB,wBAAgB;AAChB,wBAAgB;AAChB,wBAAgB;AAGf,QAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAChD,YAAM,IAAI,UAAU,iCAAiC;AAAA,IACtD;AAEA,UAAM,UAAU,OAAO,QAAQ,KAAK;AACpC,QAAI,QAAQ,WAAW,GAAG;AACzB,YAAM,IAAI,UAAU,kCAAkC;AAAA,IACvD;AAEA,UAAM,OAAO,OAAO,QAAQ,GAAG;AAC/B,QAAI,SAAS,YAAY,SAAS,UAAU;AAC3C,YAAM,IAAI,UAAU,2DAA2D;AAAA,IAChF;AAEA,SAAK,OAAO;AACZ,SAAK,QAAQ;AAEb,QAAI,SAAS,UAAU;AACtB,WAAK,OAAO;AAEZ,UAAI,OAAO;AACX,iBAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AACnC,YAAI,OAAO,UAAU;AAAU,gBAAM,IAAI,UAAU,iBAAiB,mCAAmC;AACvG,YAAI,WAAW,QAAQ;AAAI,gBAAM,IAAI,WAAW,iBAAiB,gDAAgD;AACjH,YAAI,SAAS;AAAG,gBAAM,IAAI,WAAW,iBAAiB,uCAAuC;AAC7F,gBAAQ;AAAA,MACT;AAEA,WAAK,OAAO;AAAA,IACb,OAAO;AACN,WAAK,OAAO;AAEZ,UAAI,OAAO;AACX,iBAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AACnC,YAAI,OAAO,UAAU;AAAU,gBAAM,IAAI,UAAU,iBAAiB,mCAAmC;AACvG,YAAI,SAAS;AAAI,gBAAM,IAAI,WAAW,iBAAiB,uCAAuC;AAC9F,gBAAQ;AAAA,MACT;AAEA,WAAK,OAAO;AAAA,IACb;AAAA,EACD;AAAA,EAWO,QAAQ,YAAoD;AAClE,YAAQ,OAAO,YAAY;AAAA,MAC1B,KAAK;AACJ,YAAK,cAAyB,KAAK;AAAO,iBAAO,KAAK,MAAM;AAC5D,cAAM,IAAI,WAAW,mEAAmE;AAAA,MACzF,KAAK,KAAK;AACT,eAAS,aAAiC,KAAK;AAAA,MAChD,KAAK;AACJ,YAAI,MAAM,QAAQ,UAAU;AAAG,iBAAO,WAAW,OAAO,CAAC,KAAK,UAAU,KAAK,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI;AAC5G,cAAM,IAAI,UAAU,+CAA+C;AAAA,MACpE;AACC,cAAM,IAAI,UAAU,4DAA4D,KAAK,oBAAoB;AAAA,IAC3G;AAAA,EACD;AAAA,EAQO,IAAI,OAA8B,MAAsC;AAC9E,YAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK;AAAA,EAC5D;AAAA,EAQO,IAAI,OAA8B,MAAsC;AAC9E,UAAM,WAAW,KAAK,QAAQ,IAAI;AAClC,YAAQ,KAAK,QAAQ,KAAK,IAAI,cAAc;AAAA,EAC7C;AAAA,EAoBO,WAAW,OAA+C;AAChE,WAAO,KAAK,WAAW,KAAK,MAAM,KAAK;AAAA,EACxC;AAAA,EAgBO,SAAS,QAA2D;AAC1E,QAAI,QAAQ,KAAK;AACjB,eAAW,cAAc,QAAQ;AAChC,cAAS,QAAQ,KAAK,QAAQ,UAAU;AAAA,IACzC;AAEA,WAAO;AAAA,EACR;AAAA,EAoBO,aAAa,aAAoC,QAA2D;AAClH,QAAI,QAAQ,KAAK,QAAQ,QAAQ;AACjC,eAAW,cAAc,QAAQ;AAChC,cAAS,QAAQ,KAAK,QAAQ,UAAU;AAAA,IACzC;AAEA,WAAO;AAAA,EACR;AAAA,EAiBO,WAAW,GAA0B,GAA2C;AACtF,WAAQ,KAAK,QAAQ,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC;AAAA,EAC1C;AAAA,EAoBO,oBAAoB,GAA0B,GAA2C;AAC/F,WAAQ,KAAK,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC;AAAA,EACzC;AAAA,EAmBO,QAAQ,OAA+C;AAC7D,UAAM,OAAO,KAAK,QAAQ,KAAK;AAC/B,UAAM,OAAwB,CAAC;AAC/B,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,KAAK,GAAG;AAEpD,WAAK,OAAO,SAAS;AAAK,aAAK,KAAK,GAAG;AAAA,IACxC;AAEA,WAAO;AAAA,EACR;AAAA,EAyBO,SAAS,OAA4D;AAC3E,UAAM,OAAO,KAAK,QAAQ,KAAK;AAC/B,WAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,OAAO,SAAS,GAAG,CAAC,CAAC;AAAA,EACtG;AACD;AAvQa","sourcesContent":["export class BitField<Flags extends Record<string, number> | Record<string, bigint>> {\n\tpublic readonly type: Flags[keyof Flags] extends number ? 'number' : 'bigint';\n\tpublic readonly zero: Flags[keyof Flags] extends number ? 0 : 0n;\n\tpublic readonly mask: ValueType<this>;\n\tpublic readonly flags: Flags;\n\n\tpublic constructor(flags: Readonly<Flags>) {\n\t\tif (typeof flags !== 'object' || flags === null) {\n\t\t\tthrow new TypeError('flags must be a non-null object');\n\t\t}\n\n\t\tconst entries = Object.entries(flags) as [string, Flags[keyof Flags]][];\n\t\tif (entries.length === 0) {\n\t\t\tthrow new TypeError('flags must be a non-empty object');\n\t\t}\n\n\t\tconst type = typeof entries[0][1];\n\t\tif (type !== 'number' && type !== 'bigint') {\n\t\t\tthrow new TypeError('A bitfield can only use numbers or bigints for its values');\n\t\t}\n\n\t\tthis.type = type as any;\n\t\tthis.flags = flags;\n\n\t\tif (type === 'number') {\n\t\t\tthis.zero = 0 as any;\n\n\t\t\tlet mask = 0;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'number') throw new TypeError(`The property \"${key}\" does not resolve to a number`);\n\t\t\t\tif (value !== (value | 0)) throw new RangeError(`The property \"${key}\" does not resolve to a safe bitfield value`);\n\t\t\t\tif (value <= 0) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t} else {\n\t\t\tthis.zero = 0n as any;\n\n\t\t\tlet mask = 0n;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'bigint') throw new TypeError(`The property \"${key}\" does not resolve to a bigint`);\n\t\t\t\tif (value <= 0n) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves a:\n\t * - `string`: If it's a property of {@link Flags}.\n\t * - `number`: If the BitField processes `number` primitives.\n\t * - `bigint`: If the BitField processes `bigint` primitives.\n\t * - `Array`: Resolves recursively.\n\t * @param resolvable The value to resolve.\n\t * @returns The resolved value.\n\t */\n\tpublic resolve(resolvable: ValueResolvable<this>): ValueType<this> {\n\t\tswitch (typeof resolvable) {\n\t\t\tcase 'string':\n\t\t\t\tif ((resolvable as string) in this.flags) return this.flags[resolvable as keyof Flags] as any;\n\t\t\t\tthrow new RangeError('Received a name that could not be resolved to a property of flags');\n\t\t\tcase this.type:\n\t\t\t\treturn ((resolvable as ValueType<this>) & this.mask) as any;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(resolvable)) return resolvable.reduce((acc, value) => this.resolve(value) | acc, this.zero);\n\t\t\t\tthrow new TypeError('Received an object value that is not an Array');\n\t\t\tdefault:\n\t\t\t\tthrow new TypeError(`Received a value that is not either type \"string\", type \"${this.type}\", or an Array`);\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether or not `field` contains any of the bits from `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.\n\t */\n\tpublic any(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\treturn (this.resolve(field) & this.resolve(bits)) !== this.zero;\n\t}\n\n\t/**\n\t * Checks whether or not `field` is a superset of or equal to `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.\n\t */\n\tpublic has(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\tconst resolved = this.resolve(bits);\n\t\treturn (this.resolve(field) & resolved) === resolved;\n\t}\n\n\t/**\n\t * Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)\n\t * that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.\n\t * @param field The bits to get the complement of.\n\t * @returns The complement of `field`, also denoted `AαΆ` or `A'`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.complement(0b0100);\n\t * // 0b1011\n\t * ```\n\t */\n\tpublic complement(field: ValueResolvable<this>): ValueType<this> {\n\t\treturn this.difference(this.mask, field);\n\t}\n\n\t/**\n\t * Makes a union of all the bits.\n\t * @param fields The bits to create a union of.\n\t * @returns The result of combining all bits together, also denoted as `β
β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.union(0b0001, 0b0100);\n\t * // 0b0101\n\t *\n\t * bitfield.union(0b1100, 0b0001, 0b0010);\n\t * // 0b1111\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}\n\t */\n\tpublic union(...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.zero as ValueType<this>;\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field | this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Makes an intersection of all the bits.\n\t * @param bitfield The first field.\n\t * @param fields The bits to intersect with `bitfield`.\n\t * @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.intersection(0b0001, 0b0100);\n\t * // 0b0000\n\t *\n\t * bitfield.intersection(0b1100, 0b0100);\n\t * // 0b0100\n\t *\n\t * bitfield.intersection(0b1101, 0b0101, 0b1100);\n\t * // 0b0100\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}\n\t */\n\tpublic intersection(bitfield: ValueResolvable<this>, ...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.resolve(bitfield);\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field & this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Removes from `a` the bits that exist in `b`.\n\t * @param a The first field.\n\t * @param b The bits to remove from `a`.\n\t * @returns The result of `a β b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.difference(0b1100, 0b0100);\n\t * // 0b1000\n\t *\n\t * bitfield.difference(0b1111, 0b0110);\n\t * // 0b1001\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}\n\t */\n\tpublic difference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) & ~this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of\n\t * elements which are in either of the sets, but not in their intersection. As such, this is the result of\n\t * `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.\n\t * @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`\n\t * @param a The first field.\n\t * @param b The second field.\n\t * @returns The result of computing `a Ξ b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.symmetricDifference(0b1100, 0b0011);\n\t * // 0b1111\n\t *\n\t * bitfield.symmetricDifference(0b1101, 0b1011);\n\t * // 0b0110\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}\n\t */\n\tpublic symmetricDifference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) ^ this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.\n\t * @param field The field to convert to an array.\n\t * @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toArray(0b0101);\n\t * // ['Read', 'Edit']\n\t * ```\n\t */\n\tpublic toArray(field: ValueResolvable<this>): (keyof Flags)[] {\n\t\tconst bits = this.resolve(field);\n\t\tconst keys: (keyof Flags)[] = [];\n\t\tfor (const [key, bit] of Object.entries(this.flags)) {\n\t\t\t// Inline `.has` code for lower overhead:\n\t\t\tif ((bits & bit) === bit) keys.push(key);\n\t\t}\n\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the\n\t * flag's bit is contained in `field`.\n\t * @param field The field to convert to an object.\n\t * @returns An object with the properties of {@link Flags} which values are boolean.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toObject(0b0101);\n\t * // {\n\t * // \tRead: true,\n\t * // \tWrite: false,\n\t * // \tEdit: true,\n\t * // \tDelete: false\n\t * // }\n\t * ```\n\t */\n\tpublic toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean> {\n\t\tconst bits = this.resolve(field);\n\t\treturn Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit])) as Record<keyof Flags, boolean>;\n\t}\n}\n\ntype PrimitiveType<T> = T extends number ? number : bigint;\ntype MaybeArray<T> = T | readonly T[];\n\n/**\n * Resolves the type of the values the specified {@link BitField} takes.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;\n\n/**\n * Resolves the possible types accepted by the specified {@link BitField}.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/BitField.ts"],"names":[],"mappings":"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","sourcesContent":["export class BitField<Flags extends Record<string, number> | Record<string, bigint>> {\n\tpublic readonly type: Flags[keyof Flags] extends number ? 'number' : 'bigint';\n\tpublic readonly zero: Flags[keyof Flags] extends number ? 0 : 0n;\n\tpublic readonly mask: ValueType<this>;\n\tpublic readonly flags: Flags;\n\n\tpublic constructor(flags: Readonly<Flags>) {\n\t\tif (typeof flags !== 'object' || flags === null) {\n\t\t\tthrow new TypeError('flags must be a non-null object');\n\t\t}\n\n\t\tconst entries = Object.entries(flags) as [string, Flags[keyof Flags]][];\n\t\tif (entries.length === 0) {\n\t\t\tthrow new TypeError('flags must be a non-empty object');\n\t\t}\n\n\t\tconst type = typeof entries[0][1];\n\t\tif (type !== 'number' && type !== 'bigint') {\n\t\t\tthrow new TypeError('A bitfield can only use numbers or bigints for its values');\n\t\t}\n\n\t\tthis.type = type as any;\n\t\tthis.flags = flags;\n\n\t\tif (type === 'number') {\n\t\t\tthis.zero = 0 as any;\n\n\t\t\tlet mask = 0;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'number') throw new TypeError(`The property \"${key}\" does not resolve to a number`);\n\t\t\t\tif (value !== (value | 0)) throw new RangeError(`The property \"${key}\" does not resolve to a safe bitfield value`);\n\t\t\t\tif (value <= 0) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t} else {\n\t\t\tthis.zero = 0n as any;\n\n\t\t\tlet mask = 0n;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'bigint') throw new TypeError(`The property \"${key}\" does not resolve to a bigint`);\n\t\t\t\tif (value <= 0n) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves a:\n\t * - `string`: If it's a property of {@link Flags}.\n\t * - `number`: If the BitField processes `number` primitives.\n\t * - `bigint`: If the BitField processes `bigint` primitives.\n\t * - `Array`: Resolves recursively.\n\t * @param resolvable The value to resolve.\n\t * @returns The resolved value.\n\t */\n\tpublic resolve(resolvable: ValueResolvable<this>): ValueType<this> {\n\t\tswitch (typeof resolvable) {\n\t\t\tcase 'string':\n\t\t\t\tif ((resolvable as string) in this.flags) return this.flags[resolvable as keyof Flags] as any;\n\t\t\t\tthrow new RangeError('Received a name that could not be resolved to a property of flags');\n\t\t\tcase this.type:\n\t\t\t\treturn ((resolvable as ValueType<this>) & this.mask) as any;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(resolvable)) return resolvable.reduce((acc, value) => this.resolve(value) | acc, this.zero);\n\t\t\t\tthrow new TypeError('Received an object value that is not an Array');\n\t\t\tdefault:\n\t\t\t\tthrow new TypeError(`Received a value that is not either type \"string\", type \"${this.type}\", or an Array`);\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether or not `field` contains any of the bits from `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.\n\t */\n\tpublic any(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\treturn (this.resolve(field) & this.resolve(bits)) !== this.zero;\n\t}\n\n\t/**\n\t * Checks whether or not `field` is a superset of or equal to `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.\n\t */\n\tpublic has(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\tconst resolved = this.resolve(bits);\n\t\treturn (this.resolve(field) & resolved) === resolved;\n\t}\n\n\t/**\n\t * Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)\n\t * that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.\n\t * @param field The bits to get the complement of.\n\t * @returns The complement of `field`, also denoted `AαΆ` or `A'`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.complement(0b0100);\n\t * // 0b1011\n\t * ```\n\t */\n\tpublic complement(field: ValueResolvable<this>): ValueType<this> {\n\t\treturn this.difference(this.mask, field);\n\t}\n\n\t/**\n\t * Makes a union of all the bits.\n\t * @param fields The bits to create a union of.\n\t * @returns The result of combining all bits together, also denoted as `β
β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.union(0b0001, 0b0100);\n\t * // 0b0101\n\t *\n\t * bitfield.union(0b1100, 0b0001, 0b0010);\n\t * // 0b1111\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}\n\t */\n\tpublic union(...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.zero as ValueType<this>;\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field | this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Makes an intersection of all the bits.\n\t * @param bitfield The first field.\n\t * @param fields The bits to intersect with `bitfield`.\n\t * @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.intersection(0b0001, 0b0100);\n\t * // 0b0000\n\t *\n\t * bitfield.intersection(0b1100, 0b0100);\n\t * // 0b0100\n\t *\n\t * bitfield.intersection(0b1101, 0b0101, 0b1100);\n\t * // 0b0100\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}\n\t */\n\tpublic intersection(bitfield: ValueResolvable<this>, ...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.resolve(bitfield);\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field & this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Removes from `a` the bits that exist in `b`.\n\t * @param a The first field.\n\t * @param b The bits to remove from `a`.\n\t * @returns The result of `a β b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.difference(0b1100, 0b0100);\n\t * // 0b1000\n\t *\n\t * bitfield.difference(0b1111, 0b0110);\n\t * // 0b1001\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}\n\t */\n\tpublic difference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) & ~this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of\n\t * elements which are in either of the sets, but not in their intersection. As such, this is the result of\n\t * `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.\n\t * @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`\n\t * @param a The first field.\n\t * @param b The second field.\n\t * @returns The result of computing `a Ξ b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.symmetricDifference(0b1100, 0b0011);\n\t * // 0b1111\n\t *\n\t * bitfield.symmetricDifference(0b1101, 0b1011);\n\t * // 0b0110\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}\n\t */\n\tpublic symmetricDifference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) ^ this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.\n\t * @param field The field to convert to an array.\n\t * @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toArray(0b0101);\n\t * // ['Read', 'Edit']\n\t * ```\n\t */\n\tpublic toArray(field: ValueResolvable<this>): (keyof Flags)[] {\n\t\tconst bits = this.resolve(field);\n\t\tconst keys: (keyof Flags)[] = [];\n\t\tfor (const [key, bit] of Object.entries(this.flags)) {\n\t\t\t// Inline `.has` code for lower overhead:\n\t\t\tif ((bits & bit) === bit) keys.push(key);\n\t\t}\n\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the\n\t * flag's bit is contained in `field`.\n\t * @param field The field to convert to an object.\n\t * @returns An object with the properties of {@link Flags} which values are boolean.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toObject(0b0101);\n\t * // {\n\t * // \tRead: true,\n\t * // \tWrite: false,\n\t * // \tEdit: true,\n\t * // \tDelete: false\n\t * // }\n\t * ```\n\t */\n\tpublic toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean> {\n\t\tconst bits = this.resolve(field);\n\t\treturn Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit])) as Record<keyof Flags, boolean>;\n\t}\n}\n\ntype PrimitiveType<T> = T extends number ? number : bigint;\ntype MaybeArray<T> = T | readonly T[];\n\n/**\n * Resolves the type of the values the specified {@link BitField} takes.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;\n\n/**\n * Resolves the possible types accepted by the specified {@link BitField}.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var __defProp = Object.defineProperty;
|
|
6
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
5
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -56,6 +54,15 @@ var BitField = class {
|
|
|
56
54
|
this.mask = mask;
|
|
57
55
|
}
|
|
58
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolves a:
|
|
59
|
+
* - `string`: If it's a property of {@link Flags}.
|
|
60
|
+
* - `number`: If the BitField processes `number` primitives.
|
|
61
|
+
* - `bigint`: If the BitField processes `bigint` primitives.
|
|
62
|
+
* - `Array`: Resolves recursively.
|
|
63
|
+
* @param resolvable The value to resolve.
|
|
64
|
+
* @returns The resolved value.
|
|
65
|
+
*/
|
|
59
66
|
resolve(resolvable) {
|
|
60
67
|
switch (typeof resolvable) {
|
|
61
68
|
case "string":
|
|
@@ -72,16 +79,60 @@ var BitField = class {
|
|
|
72
79
|
throw new TypeError(`Received a value that is not either type "string", type "${this.type}", or an Array`);
|
|
73
80
|
}
|
|
74
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Checks whether or not `field` contains any of the bits from `bits`.
|
|
84
|
+
* @param field The bits to compare the bits from.
|
|
85
|
+
* @param bits The bits to compare with.
|
|
86
|
+
* @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.
|
|
87
|
+
*/
|
|
75
88
|
any(field, bits) {
|
|
76
89
|
return (this.resolve(field) & this.resolve(bits)) !== this.zero;
|
|
77
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Checks whether or not `field` is a superset of or equal to `bits`.
|
|
93
|
+
* @param field The bits to compare the bits from.
|
|
94
|
+
* @param bits The bits to compare with.
|
|
95
|
+
* @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.
|
|
96
|
+
*/
|
|
78
97
|
has(field, bits) {
|
|
79
98
|
const resolved = this.resolve(bits);
|
|
80
99
|
return (this.resolve(field) & resolved) === resolved;
|
|
81
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)
|
|
103
|
+
* that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.
|
|
104
|
+
* @param field The bits to get the complement of.
|
|
105
|
+
* @returns The complement of `field`, also denoted `AαΆ` or `A'`.
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const bitfield = new BitField({
|
|
109
|
+
* Read: 0b0001,
|
|
110
|
+
* Write: 0b0010,
|
|
111
|
+
* Edit: 0b0100,
|
|
112
|
+
* Delete: 0b1000
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* bitfield.complement(0b0100);
|
|
116
|
+
* // 0b1011
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
82
119
|
complement(field) {
|
|
83
120
|
return this.difference(this.mask, field);
|
|
84
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Makes a union of all the bits.
|
|
124
|
+
* @param fields The bits to create a union of.
|
|
125
|
+
* @returns The result of combining all bits together, also denoted as `β
β fields`.
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* bitfield.union(0b0001, 0b0100);
|
|
129
|
+
* // 0b0101
|
|
130
|
+
*
|
|
131
|
+
* bitfield.union(0b1100, 0b0001, 0b0010);
|
|
132
|
+
* // 0b1111
|
|
133
|
+
* ```
|
|
134
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}
|
|
135
|
+
*/
|
|
85
136
|
union(...fields) {
|
|
86
137
|
let field = this.zero;
|
|
87
138
|
for (const resolvable of fields) {
|
|
@@ -89,6 +140,24 @@ var BitField = class {
|
|
|
89
140
|
}
|
|
90
141
|
return field;
|
|
91
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Makes an intersection of all the bits.
|
|
145
|
+
* @param bitfield The first field.
|
|
146
|
+
* @param fields The bits to intersect with `bitfield`.
|
|
147
|
+
* @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* bitfield.intersection(0b0001, 0b0100);
|
|
151
|
+
* // 0b0000
|
|
152
|
+
*
|
|
153
|
+
* bitfield.intersection(0b1100, 0b0100);
|
|
154
|
+
* // 0b0100
|
|
155
|
+
*
|
|
156
|
+
* bitfield.intersection(0b1101, 0b0101, 0b1100);
|
|
157
|
+
* // 0b0100
|
|
158
|
+
* ```
|
|
159
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}
|
|
160
|
+
*/
|
|
92
161
|
intersection(bitfield, ...fields) {
|
|
93
162
|
let field = this.resolve(bitfield);
|
|
94
163
|
for (const resolvable of fields) {
|
|
@@ -96,12 +165,62 @@ var BitField = class {
|
|
|
96
165
|
}
|
|
97
166
|
return field;
|
|
98
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Removes from `a` the bits that exist in `b`.
|
|
170
|
+
* @param a The first field.
|
|
171
|
+
* @param b The bits to remove from `a`.
|
|
172
|
+
* @returns The result of `a β b`.
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* bitfield.difference(0b1100, 0b0100);
|
|
176
|
+
* // 0b1000
|
|
177
|
+
*
|
|
178
|
+
* bitfield.difference(0b1111, 0b0110);
|
|
179
|
+
* // 0b1001
|
|
180
|
+
* ```
|
|
181
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}
|
|
182
|
+
*/
|
|
99
183
|
difference(a, b) {
|
|
100
184
|
return this.resolve(a) & ~this.resolve(b);
|
|
101
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of
|
|
188
|
+
* elements which are in either of the sets, but not in their intersection. As such, this is the result of
|
|
189
|
+
* `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.
|
|
190
|
+
* @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`
|
|
191
|
+
* @param a The first field.
|
|
192
|
+
* @param b The second field.
|
|
193
|
+
* @returns The result of computing `a Ξ b`.
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* bitfield.symmetricDifference(0b1100, 0b0011);
|
|
197
|
+
* // 0b1111
|
|
198
|
+
*
|
|
199
|
+
* bitfield.symmetricDifference(0b1101, 0b1011);
|
|
200
|
+
* // 0b0110
|
|
201
|
+
* ```
|
|
202
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}
|
|
203
|
+
*/
|
|
102
204
|
symmetricDifference(a, b) {
|
|
103
205
|
return this.resolve(a) ^ this.resolve(b);
|
|
104
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.
|
|
209
|
+
* @param field The field to convert to an array.
|
|
210
|
+
* @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* const bitfield = new BitField({
|
|
214
|
+
* Read: 0b0001,
|
|
215
|
+
* Write: 0b0010,
|
|
216
|
+
* Edit: 0b0100,
|
|
217
|
+
* Delete: 0b1000
|
|
218
|
+
* });
|
|
219
|
+
*
|
|
220
|
+
* bitfield.toArray(0b0101);
|
|
221
|
+
* // ['Read', 'Edit']
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
105
224
|
toArray(field) {
|
|
106
225
|
const bits = this.resolve(field);
|
|
107
226
|
const keys = [];
|
|
@@ -111,6 +230,29 @@ var BitField = class {
|
|
|
111
230
|
}
|
|
112
231
|
return keys;
|
|
113
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the
|
|
235
|
+
* flag's bit is contained in `field`.
|
|
236
|
+
* @param field The field to convert to an object.
|
|
237
|
+
* @returns An object with the properties of {@link Flags} which values are boolean.
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* const bitfield = new BitField({
|
|
241
|
+
* Read: 0b0001,
|
|
242
|
+
* Write: 0b0010,
|
|
243
|
+
* Edit: 0b0100,
|
|
244
|
+
* Delete: 0b1000
|
|
245
|
+
* });
|
|
246
|
+
*
|
|
247
|
+
* bitfield.toObject(0b0101);
|
|
248
|
+
* // {
|
|
249
|
+
* // Read: true,
|
|
250
|
+
* // Write: false,
|
|
251
|
+
* // Edit: true,
|
|
252
|
+
* // Delete: false
|
|
253
|
+
* // }
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
114
256
|
toObject(field) {
|
|
115
257
|
const bits = this.resolve(field);
|
|
116
258
|
return Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit]));
|
|
@@ -119,4 +261,5 @@ var BitField = class {
|
|
|
119
261
|
__name(BitField, "BitField");
|
|
120
262
|
|
|
121
263
|
exports.BitField = BitField;
|
|
264
|
+
//# sourceMappingURL=out.js.map
|
|
122
265
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/BitField.ts"],"names":[],"mappings":"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","sourcesContent":["export class BitField<Flags extends Record<string, number> | Record<string, bigint>> {\n\tpublic readonly type: Flags[keyof Flags] extends number ? 'number' : 'bigint';\n\tpublic readonly zero: Flags[keyof Flags] extends number ? 0 : 0n;\n\tpublic readonly mask: ValueType<this>;\n\tpublic readonly flags: Flags;\n\n\tpublic constructor(flags: Readonly<Flags>) {\n\t\tif (typeof flags !== 'object' || flags === null) {\n\t\t\tthrow new TypeError('flags must be a non-null object');\n\t\t}\n\n\t\tconst entries = Object.entries(flags) as [string, Flags[keyof Flags]][];\n\t\tif (entries.length === 0) {\n\t\t\tthrow new TypeError('flags must be a non-empty object');\n\t\t}\n\n\t\tconst type = typeof entries[0][1];\n\t\tif (type !== 'number' && type !== 'bigint') {\n\t\t\tthrow new TypeError('A bitfield can only use numbers or bigints for its values');\n\t\t}\n\n\t\tthis.type = type as any;\n\t\tthis.flags = flags;\n\n\t\tif (type === 'number') {\n\t\t\tthis.zero = 0 as any;\n\n\t\t\tlet mask = 0;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'number') throw new TypeError(`The property \"${key}\" does not resolve to a number`);\n\t\t\t\tif (value !== (value | 0)) throw new RangeError(`The property \"${key}\" does not resolve to a safe bitfield value`);\n\t\t\t\tif (value <= 0) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t} else {\n\t\t\tthis.zero = 0n as any;\n\n\t\t\tlet mask = 0n;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'bigint') throw new TypeError(`The property \"${key}\" does not resolve to a bigint`);\n\t\t\t\tif (value <= 0n) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves a:\n\t * - `string`: If it's a property of {@link Flags}.\n\t * - `number`: If the BitField processes `number` primitives.\n\t * - `bigint`: If the BitField processes `bigint` primitives.\n\t * - `Array`: Resolves recursively.\n\t * @param resolvable The value to resolve.\n\t * @returns The resolved value.\n\t */\n\tpublic resolve(resolvable: ValueResolvable<this>): ValueType<this> {\n\t\tswitch (typeof resolvable) {\n\t\t\tcase 'string':\n\t\t\t\tif ((resolvable as string) in this.flags) return this.flags[resolvable as keyof Flags] as any;\n\t\t\t\tthrow new RangeError('Received a name that could not be resolved to a property of flags');\n\t\t\tcase this.type:\n\t\t\t\treturn ((resolvable as ValueType<this>) & this.mask) as any;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(resolvable)) return resolvable.reduce((acc, value) => this.resolve(value) | acc, this.zero);\n\t\t\t\tthrow new TypeError('Received an object value that is not an Array');\n\t\t\tdefault:\n\t\t\t\tthrow new TypeError(`Received a value that is not either type \"string\", type \"${this.type}\", or an Array`);\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether or not `field` contains any of the bits from `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.\n\t */\n\tpublic any(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\treturn (this.resolve(field) & this.resolve(bits)) !== this.zero;\n\t}\n\n\t/**\n\t * Checks whether or not `field` is a superset of or equal to `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.\n\t */\n\tpublic has(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\tconst resolved = this.resolve(bits);\n\t\treturn (this.resolve(field) & resolved) === resolved;\n\t}\n\n\t/**\n\t * Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)\n\t * that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.\n\t * @param field The bits to get the complement of.\n\t * @returns The complement of `field`, also denoted `AαΆ` or `A'`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.complement(0b0100);\n\t * // 0b1011\n\t * ```\n\t */\n\tpublic complement(field: ValueResolvable<this>): ValueType<this> {\n\t\treturn this.difference(this.mask, field);\n\t}\n\n\t/**\n\t * Makes a union of all the bits.\n\t * @param fields The bits to create a union of.\n\t * @returns The result of combining all bits together, also denoted as `β
β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.union(0b0001, 0b0100);\n\t * // 0b0101\n\t *\n\t * bitfield.union(0b1100, 0b0001, 0b0010);\n\t * // 0b1111\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}\n\t */\n\tpublic union(...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.zero as ValueType<this>;\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field | this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Makes an intersection of all the bits.\n\t * @param bitfield The first field.\n\t * @param fields The bits to intersect with `bitfield`.\n\t * @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.intersection(0b0001, 0b0100);\n\t * // 0b0000\n\t *\n\t * bitfield.intersection(0b1100, 0b0100);\n\t * // 0b0100\n\t *\n\t * bitfield.intersection(0b1101, 0b0101, 0b1100);\n\t * // 0b0100\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}\n\t */\n\tpublic intersection(bitfield: ValueResolvable<this>, ...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.resolve(bitfield);\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field & this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Removes from `a` the bits that exist in `b`.\n\t * @param a The first field.\n\t * @param b The bits to remove from `a`.\n\t * @returns The result of `a β b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.difference(0b1100, 0b0100);\n\t * // 0b1000\n\t *\n\t * bitfield.difference(0b1111, 0b0110);\n\t * // 0b1001\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}\n\t */\n\tpublic difference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) & ~this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of\n\t * elements which are in either of the sets, but not in their intersection. As such, this is the result of\n\t * `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.\n\t * @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`\n\t * @param a The first field.\n\t * @param b The second field.\n\t * @returns The result of computing `a Ξ b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.symmetricDifference(0b1100, 0b0011);\n\t * // 0b1111\n\t *\n\t * bitfield.symmetricDifference(0b1101, 0b1011);\n\t * // 0b0110\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}\n\t */\n\tpublic symmetricDifference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) ^ this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.\n\t * @param field The field to convert to an array.\n\t * @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toArray(0b0101);\n\t * // ['Read', 'Edit']\n\t * ```\n\t */\n\tpublic toArray(field: ValueResolvable<this>): (keyof Flags)[] {\n\t\tconst bits = this.resolve(field);\n\t\tconst keys: (keyof Flags)[] = [];\n\t\tfor (const [key, bit] of Object.entries(this.flags)) {\n\t\t\t// Inline `.has` code for lower overhead:\n\t\t\tif ((bits & bit) === bit) keys.push(key);\n\t\t}\n\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the\n\t * flag's bit is contained in `field`.\n\t * @param field The field to convert to an object.\n\t * @returns An object with the properties of {@link Flags} which values are boolean.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toObject(0b0101);\n\t * // {\n\t * // \tRead: true,\n\t * // \tWrite: false,\n\t * // \tEdit: true,\n\t * // \tDelete: false\n\t * // }\n\t * ```\n\t */\n\tpublic toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean> {\n\t\tconst bits = this.resolve(field);\n\t\treturn Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit])) as Record<keyof Flags, boolean>;\n\t}\n}\n\ntype PrimitiveType<T> = T extends number ? number : bigint;\ntype MaybeArray<T> = T | readonly T[];\n\n/**\n * Resolves the type of the values the specified {@link BitField} takes.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;\n\n/**\n * Resolves the possible types accepted by the specified {@link BitField}.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/BitField.ts"],"names":[],"mappings":"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","sourcesContent":["export class BitField<Flags extends Record<string, number> | Record<string, bigint>> {\n\tpublic readonly type: Flags[keyof Flags] extends number ? 'number' : 'bigint';\n\tpublic readonly zero: Flags[keyof Flags] extends number ? 0 : 0n;\n\tpublic readonly mask: ValueType<this>;\n\tpublic readonly flags: Flags;\n\n\tpublic constructor(flags: Readonly<Flags>) {\n\t\tif (typeof flags !== 'object' || flags === null) {\n\t\t\tthrow new TypeError('flags must be a non-null object');\n\t\t}\n\n\t\tconst entries = Object.entries(flags) as [string, Flags[keyof Flags]][];\n\t\tif (entries.length === 0) {\n\t\t\tthrow new TypeError('flags must be a non-empty object');\n\t\t}\n\n\t\tconst type = typeof entries[0][1];\n\t\tif (type !== 'number' && type !== 'bigint') {\n\t\t\tthrow new TypeError('A bitfield can only use numbers or bigints for its values');\n\t\t}\n\n\t\tthis.type = type as any;\n\t\tthis.flags = flags;\n\n\t\tif (type === 'number') {\n\t\t\tthis.zero = 0 as any;\n\n\t\t\tlet mask = 0;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'number') throw new TypeError(`The property \"${key}\" does not resolve to a number`);\n\t\t\t\tif (value !== (value | 0)) throw new RangeError(`The property \"${key}\" does not resolve to a safe bitfield value`);\n\t\t\t\tif (value <= 0) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t} else {\n\t\t\tthis.zero = 0n as any;\n\n\t\t\tlet mask = 0n;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'bigint') throw new TypeError(`The property \"${key}\" does not resolve to a bigint`);\n\t\t\t\tif (value <= 0n) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves a:\n\t * - `string`: If it's a property of {@link Flags}.\n\t * - `number`: If the BitField processes `number` primitives.\n\t * - `bigint`: If the BitField processes `bigint` primitives.\n\t * - `Array`: Resolves recursively.\n\t * @param resolvable The value to resolve.\n\t * @returns The resolved value.\n\t */\n\tpublic resolve(resolvable: ValueResolvable<this>): ValueType<this> {\n\t\tswitch (typeof resolvable) {\n\t\t\tcase 'string':\n\t\t\t\tif ((resolvable as string) in this.flags) return this.flags[resolvable as keyof Flags] as any;\n\t\t\t\tthrow new RangeError('Received a name that could not be resolved to a property of flags');\n\t\t\tcase this.type:\n\t\t\t\treturn ((resolvable as ValueType<this>) & this.mask) as any;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(resolvable)) return resolvable.reduce((acc, value) => this.resolve(value) | acc, this.zero);\n\t\t\t\tthrow new TypeError('Received an object value that is not an Array');\n\t\t\tdefault:\n\t\t\t\tthrow new TypeError(`Received a value that is not either type \"string\", type \"${this.type}\", or an Array`);\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether or not `field` contains any of the bits from `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.\n\t */\n\tpublic any(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\treturn (this.resolve(field) & this.resolve(bits)) !== this.zero;\n\t}\n\n\t/**\n\t * Checks whether or not `field` is a superset of or equal to `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.\n\t */\n\tpublic has(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\tconst resolved = this.resolve(bits);\n\t\treturn (this.resolve(field) & resolved) === resolved;\n\t}\n\n\t/**\n\t * Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)\n\t * that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.\n\t * @param field The bits to get the complement of.\n\t * @returns The complement of `field`, also denoted `AαΆ` or `A'`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.complement(0b0100);\n\t * // 0b1011\n\t * ```\n\t */\n\tpublic complement(field: ValueResolvable<this>): ValueType<this> {\n\t\treturn this.difference(this.mask, field);\n\t}\n\n\t/**\n\t * Makes a union of all the bits.\n\t * @param fields The bits to create a union of.\n\t * @returns The result of combining all bits together, also denoted as `β
β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.union(0b0001, 0b0100);\n\t * // 0b0101\n\t *\n\t * bitfield.union(0b1100, 0b0001, 0b0010);\n\t * // 0b1111\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}\n\t */\n\tpublic union(...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.zero as ValueType<this>;\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field | this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Makes an intersection of all the bits.\n\t * @param bitfield The first field.\n\t * @param fields The bits to intersect with `bitfield`.\n\t * @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.intersection(0b0001, 0b0100);\n\t * // 0b0000\n\t *\n\t * bitfield.intersection(0b1100, 0b0100);\n\t * // 0b0100\n\t *\n\t * bitfield.intersection(0b1101, 0b0101, 0b1100);\n\t * // 0b0100\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}\n\t */\n\tpublic intersection(bitfield: ValueResolvable<this>, ...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.resolve(bitfield);\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field & this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Removes from `a` the bits that exist in `b`.\n\t * @param a The first field.\n\t * @param b The bits to remove from `a`.\n\t * @returns The result of `a β b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.difference(0b1100, 0b0100);\n\t * // 0b1000\n\t *\n\t * bitfield.difference(0b1111, 0b0110);\n\t * // 0b1001\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}\n\t */\n\tpublic difference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) & ~this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of\n\t * elements which are in either of the sets, but not in their intersection. As such, this is the result of\n\t * `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.\n\t * @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`\n\t * @param a The first field.\n\t * @param b The second field.\n\t * @returns The result of computing `a Ξ b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.symmetricDifference(0b1100, 0b0011);\n\t * // 0b1111\n\t *\n\t * bitfield.symmetricDifference(0b1101, 0b1011);\n\t * // 0b0110\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}\n\t */\n\tpublic symmetricDifference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) ^ this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.\n\t * @param field The field to convert to an array.\n\t * @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toArray(0b0101);\n\t * // ['Read', 'Edit']\n\t * ```\n\t */\n\tpublic toArray(field: ValueResolvable<this>): (keyof Flags)[] {\n\t\tconst bits = this.resolve(field);\n\t\tconst keys: (keyof Flags)[] = [];\n\t\tfor (const [key, bit] of Object.entries(this.flags)) {\n\t\t\t// Inline `.has` code for lower overhead:\n\t\t\tif ((bits & bit) === bit) keys.push(key);\n\t\t}\n\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the\n\t * flag's bit is contained in `field`.\n\t * @param field The field to convert to an object.\n\t * @returns An object with the properties of {@link Flags} which values are boolean.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toObject(0b0101);\n\t * // {\n\t * // \tRead: true,\n\t * // \tWrite: false,\n\t * // \tEdit: true,\n\t * // \tDelete: false\n\t * // }\n\t * ```\n\t */\n\tpublic toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean> {\n\t\tconst bits = this.resolve(field);\n\t\treturn Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit])) as Record<keyof Flags, boolean>;\n\t}\n}\n\ntype PrimitiveType<T> = T extends number ? number : bigint;\ntype MaybeArray<T> = T | readonly T[];\n\n/**\n * Resolves the type of the values the specified {@link BitField} takes.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;\n\n/**\n * Resolves the possible types accepted by the specified {@link BitField}.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -52,6 +52,15 @@ var BitField = class {
|
|
|
52
52
|
this.mask = mask;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolves a:
|
|
57
|
+
* - `string`: If it's a property of {@link Flags}.
|
|
58
|
+
* - `number`: If the BitField processes `number` primitives.
|
|
59
|
+
* - `bigint`: If the BitField processes `bigint` primitives.
|
|
60
|
+
* - `Array`: Resolves recursively.
|
|
61
|
+
* @param resolvable The value to resolve.
|
|
62
|
+
* @returns The resolved value.
|
|
63
|
+
*/
|
|
55
64
|
resolve(resolvable) {
|
|
56
65
|
switch (typeof resolvable) {
|
|
57
66
|
case "string":
|
|
@@ -68,16 +77,60 @@ var BitField = class {
|
|
|
68
77
|
throw new TypeError(`Received a value that is not either type "string", type "${this.type}", or an Array`);
|
|
69
78
|
}
|
|
70
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Checks whether or not `field` contains any of the bits from `bits`.
|
|
82
|
+
* @param field The bits to compare the bits from.
|
|
83
|
+
* @param bits The bits to compare with.
|
|
84
|
+
* @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.
|
|
85
|
+
*/
|
|
71
86
|
any(field, bits) {
|
|
72
87
|
return (this.resolve(field) & this.resolve(bits)) !== this.zero;
|
|
73
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Checks whether or not `field` is a superset of or equal to `bits`.
|
|
91
|
+
* @param field The bits to compare the bits from.
|
|
92
|
+
* @param bits The bits to compare with.
|
|
93
|
+
* @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.
|
|
94
|
+
*/
|
|
74
95
|
has(field, bits) {
|
|
75
96
|
const resolved = this.resolve(bits);
|
|
76
97
|
return (this.resolve(field) & resolved) === resolved;
|
|
77
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)
|
|
101
|
+
* that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.
|
|
102
|
+
* @param field The bits to get the complement of.
|
|
103
|
+
* @returns The complement of `field`, also denoted `AαΆ` or `A'`.
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const bitfield = new BitField({
|
|
107
|
+
* Read: 0b0001,
|
|
108
|
+
* Write: 0b0010,
|
|
109
|
+
* Edit: 0b0100,
|
|
110
|
+
* Delete: 0b1000
|
|
111
|
+
* });
|
|
112
|
+
*
|
|
113
|
+
* bitfield.complement(0b0100);
|
|
114
|
+
* // 0b1011
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
78
117
|
complement(field) {
|
|
79
118
|
return this.difference(this.mask, field);
|
|
80
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Makes a union of all the bits.
|
|
122
|
+
* @param fields The bits to create a union of.
|
|
123
|
+
* @returns The result of combining all bits together, also denoted as `β
β fields`.
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* bitfield.union(0b0001, 0b0100);
|
|
127
|
+
* // 0b0101
|
|
128
|
+
*
|
|
129
|
+
* bitfield.union(0b1100, 0b0001, 0b0010);
|
|
130
|
+
* // 0b1111
|
|
131
|
+
* ```
|
|
132
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}
|
|
133
|
+
*/
|
|
81
134
|
union(...fields) {
|
|
82
135
|
let field = this.zero;
|
|
83
136
|
for (const resolvable of fields) {
|
|
@@ -85,6 +138,24 @@ var BitField = class {
|
|
|
85
138
|
}
|
|
86
139
|
return field;
|
|
87
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Makes an intersection of all the bits.
|
|
143
|
+
* @param bitfield The first field.
|
|
144
|
+
* @param fields The bits to intersect with `bitfield`.
|
|
145
|
+
* @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* bitfield.intersection(0b0001, 0b0100);
|
|
149
|
+
* // 0b0000
|
|
150
|
+
*
|
|
151
|
+
* bitfield.intersection(0b1100, 0b0100);
|
|
152
|
+
* // 0b0100
|
|
153
|
+
*
|
|
154
|
+
* bitfield.intersection(0b1101, 0b0101, 0b1100);
|
|
155
|
+
* // 0b0100
|
|
156
|
+
* ```
|
|
157
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}
|
|
158
|
+
*/
|
|
88
159
|
intersection(bitfield, ...fields) {
|
|
89
160
|
let field = this.resolve(bitfield);
|
|
90
161
|
for (const resolvable of fields) {
|
|
@@ -92,12 +163,62 @@ var BitField = class {
|
|
|
92
163
|
}
|
|
93
164
|
return field;
|
|
94
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Removes from `a` the bits that exist in `b`.
|
|
168
|
+
* @param a The first field.
|
|
169
|
+
* @param b The bits to remove from `a`.
|
|
170
|
+
* @returns The result of `a β b`.
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* bitfield.difference(0b1100, 0b0100);
|
|
174
|
+
* // 0b1000
|
|
175
|
+
*
|
|
176
|
+
* bitfield.difference(0b1111, 0b0110);
|
|
177
|
+
* // 0b1001
|
|
178
|
+
* ```
|
|
179
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}
|
|
180
|
+
*/
|
|
95
181
|
difference(a, b) {
|
|
96
182
|
return this.resolve(a) & ~this.resolve(b);
|
|
97
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of
|
|
186
|
+
* elements which are in either of the sets, but not in their intersection. As such, this is the result of
|
|
187
|
+
* `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.
|
|
188
|
+
* @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`
|
|
189
|
+
* @param a The first field.
|
|
190
|
+
* @param b The second field.
|
|
191
|
+
* @returns The result of computing `a Ξ b`.
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* bitfield.symmetricDifference(0b1100, 0b0011);
|
|
195
|
+
* // 0b1111
|
|
196
|
+
*
|
|
197
|
+
* bitfield.symmetricDifference(0b1101, 0b1011);
|
|
198
|
+
* // 0b0110
|
|
199
|
+
* ```
|
|
200
|
+
* @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}
|
|
201
|
+
*/
|
|
98
202
|
symmetricDifference(a, b) {
|
|
99
203
|
return this.resolve(a) ^ this.resolve(b);
|
|
100
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.
|
|
207
|
+
* @param field The field to convert to an array.
|
|
208
|
+
* @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const bitfield = new BitField({
|
|
212
|
+
* Read: 0b0001,
|
|
213
|
+
* Write: 0b0010,
|
|
214
|
+
* Edit: 0b0100,
|
|
215
|
+
* Delete: 0b1000
|
|
216
|
+
* });
|
|
217
|
+
*
|
|
218
|
+
* bitfield.toArray(0b0101);
|
|
219
|
+
* // ['Read', 'Edit']
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
101
222
|
toArray(field) {
|
|
102
223
|
const bits = this.resolve(field);
|
|
103
224
|
const keys = [];
|
|
@@ -107,6 +228,29 @@ var BitField = class {
|
|
|
107
228
|
}
|
|
108
229
|
return keys;
|
|
109
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the
|
|
233
|
+
* flag's bit is contained in `field`.
|
|
234
|
+
* @param field The field to convert to an object.
|
|
235
|
+
* @returns An object with the properties of {@link Flags} which values are boolean.
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const bitfield = new BitField({
|
|
239
|
+
* Read: 0b0001,
|
|
240
|
+
* Write: 0b0010,
|
|
241
|
+
* Edit: 0b0100,
|
|
242
|
+
* Delete: 0b1000
|
|
243
|
+
* });
|
|
244
|
+
*
|
|
245
|
+
* bitfield.toObject(0b0101);
|
|
246
|
+
* // {
|
|
247
|
+
* // Read: true,
|
|
248
|
+
* // Write: false,
|
|
249
|
+
* // Edit: true,
|
|
250
|
+
* // Delete: false
|
|
251
|
+
* // }
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
110
254
|
toObject(field) {
|
|
111
255
|
const bits = this.resolve(field);
|
|
112
256
|
return Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit]));
|
|
@@ -115,4 +259,5 @@ var BitField = class {
|
|
|
115
259
|
__name(BitField, "BitField");
|
|
116
260
|
|
|
117
261
|
export { BitField };
|
|
262
|
+
//# sourceMappingURL=out.js.map
|
|
118
263
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/BitField.ts"],"names":[],"mappings":"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","sourcesContent":["export class BitField<Flags extends Record<string, number> | Record<string, bigint>> {\n\tpublic readonly type: Flags[keyof Flags] extends number ? 'number' : 'bigint';\n\tpublic readonly zero: Flags[keyof Flags] extends number ? 0 : 0n;\n\tpublic readonly mask: ValueType<this>;\n\tpublic readonly flags: Flags;\n\n\tpublic constructor(flags: Readonly<Flags>) {\n\t\tif (typeof flags !== 'object' || flags === null) {\n\t\t\tthrow new TypeError('flags must be a non-null object');\n\t\t}\n\n\t\tconst entries = Object.entries(flags) as [string, Flags[keyof Flags]][];\n\t\tif (entries.length === 0) {\n\t\t\tthrow new TypeError('flags must be a non-empty object');\n\t\t}\n\n\t\tconst type = typeof entries[0][1];\n\t\tif (type !== 'number' && type !== 'bigint') {\n\t\t\tthrow new TypeError('A bitfield can only use numbers or bigints for its values');\n\t\t}\n\n\t\tthis.type = type as any;\n\t\tthis.flags = flags;\n\n\t\tif (type === 'number') {\n\t\t\tthis.zero = 0 as any;\n\n\t\t\tlet mask = 0;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'number') throw new TypeError(`The property \"${key}\" does not resolve to a number`);\n\t\t\t\tif (value !== (value | 0)) throw new RangeError(`The property \"${key}\" does not resolve to a safe bitfield value`);\n\t\t\t\tif (value <= 0) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t} else {\n\t\t\tthis.zero = 0n as any;\n\n\t\t\tlet mask = 0n;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'bigint') throw new TypeError(`The property \"${key}\" does not resolve to a bigint`);\n\t\t\t\tif (value <= 0n) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves a:\n\t * - `string`: If it's a property of {@link Flags}.\n\t * - `number`: If the BitField processes `number` primitives.\n\t * - `bigint`: If the BitField processes `bigint` primitives.\n\t * - `Array`: Resolves recursively.\n\t * @param resolvable The value to resolve.\n\t * @returns The resolved value.\n\t */\n\tpublic resolve(resolvable: ValueResolvable<this>): ValueType<this> {\n\t\tswitch (typeof resolvable) {\n\t\t\tcase 'string':\n\t\t\t\tif ((resolvable as string) in this.flags) return this.flags[resolvable as keyof Flags] as any;\n\t\t\t\tthrow new RangeError('Received a name that could not be resolved to a property of flags');\n\t\t\tcase this.type:\n\t\t\t\treturn ((resolvable as ValueType<this>) & this.mask) as any;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(resolvable)) return resolvable.reduce((acc, value) => this.resolve(value) | acc, this.zero);\n\t\t\t\tthrow new TypeError('Received an object value that is not an Array');\n\t\t\tdefault:\n\t\t\t\tthrow new TypeError(`Received a value that is not either type \"string\", type \"${this.type}\", or an Array`);\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether or not `field` contains any of the bits from `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.\n\t */\n\tpublic any(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\treturn (this.resolve(field) & this.resolve(bits)) !== this.zero;\n\t}\n\n\t/**\n\t * Checks whether or not `field` is a superset of or equal to `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.\n\t */\n\tpublic has(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\tconst resolved = this.resolve(bits);\n\t\treturn (this.resolve(field) & resolved) === resolved;\n\t}\n\n\t/**\n\t * Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)\n\t * that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.\n\t * @param field The bits to get the complement of.\n\t * @returns The complement of `field`, also denoted `AαΆ` or `A'`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.complement(0b0100);\n\t * // 0b1011\n\t * ```\n\t */\n\tpublic complement(field: ValueResolvable<this>): ValueType<this> {\n\t\treturn this.difference(this.mask, field);\n\t}\n\n\t/**\n\t * Makes a union of all the bits.\n\t * @param fields The bits to create a union of.\n\t * @returns The result of combining all bits together, also denoted as `β
β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.union(0b0001, 0b0100);\n\t * // 0b0101\n\t *\n\t * bitfield.union(0b1100, 0b0001, 0b0010);\n\t * // 0b1111\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}\n\t */\n\tpublic union(...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.zero as ValueType<this>;\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field | this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Makes an intersection of all the bits.\n\t * @param bitfield The first field.\n\t * @param fields The bits to intersect with `bitfield`.\n\t * @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.intersection(0b0001, 0b0100);\n\t * // 0b0000\n\t *\n\t * bitfield.intersection(0b1100, 0b0100);\n\t * // 0b0100\n\t *\n\t * bitfield.intersection(0b1101, 0b0101, 0b1100);\n\t * // 0b0100\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}\n\t */\n\tpublic intersection(bitfield: ValueResolvable<this>, ...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.resolve(bitfield);\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field & this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Removes from `a` the bits that exist in `b`.\n\t * @param a The first field.\n\t * @param b The bits to remove from `a`.\n\t * @returns The result of `a β b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.difference(0b1100, 0b0100);\n\t * // 0b1000\n\t *\n\t * bitfield.difference(0b1111, 0b0110);\n\t * // 0b1001\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}\n\t */\n\tpublic difference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) & ~this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of\n\t * elements which are in either of the sets, but not in their intersection. As such, this is the result of\n\t * `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.\n\t * @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`\n\t * @param a The first field.\n\t * @param b The second field.\n\t * @returns The result of computing `a Ξ b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.symmetricDifference(0b1100, 0b0011);\n\t * // 0b1111\n\t *\n\t * bitfield.symmetricDifference(0b1101, 0b1011);\n\t * // 0b0110\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}\n\t */\n\tpublic symmetricDifference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) ^ this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.\n\t * @param field The field to convert to an array.\n\t * @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toArray(0b0101);\n\t * // ['Read', 'Edit']\n\t * ```\n\t */\n\tpublic toArray(field: ValueResolvable<this>): (keyof Flags)[] {\n\t\tconst bits = this.resolve(field);\n\t\tconst keys: (keyof Flags)[] = [];\n\t\tfor (const [key, bit] of Object.entries(this.flags)) {\n\t\t\t// Inline `.has` code for lower overhead:\n\t\t\tif ((bits & bit) === bit) keys.push(key);\n\t\t}\n\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the\n\t * flag's bit is contained in `field`.\n\t * @param field The field to convert to an object.\n\t * @returns An object with the properties of {@link Flags} which values are boolean.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toObject(0b0101);\n\t * // {\n\t * // \tRead: true,\n\t * // \tWrite: false,\n\t * // \tEdit: true,\n\t * // \tDelete: false\n\t * // }\n\t * ```\n\t */\n\tpublic toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean> {\n\t\tconst bits = this.resolve(field);\n\t\treturn Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit])) as Record<keyof Flags, boolean>;\n\t}\n}\n\ntype PrimitiveType<T> = T extends number ? number : bigint;\ntype MaybeArray<T> = T | readonly T[];\n\n/**\n * Resolves the type of the values the specified {@link BitField} takes.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;\n\n/**\n * Resolves the possible types accepted by the specified {@link BitField}.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/BitField.ts"],"names":[],"mappings":"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","sourcesContent":["export class BitField<Flags extends Record<string, number> | Record<string, bigint>> {\n\tpublic readonly type: Flags[keyof Flags] extends number ? 'number' : 'bigint';\n\tpublic readonly zero: Flags[keyof Flags] extends number ? 0 : 0n;\n\tpublic readonly mask: ValueType<this>;\n\tpublic readonly flags: Flags;\n\n\tpublic constructor(flags: Readonly<Flags>) {\n\t\tif (typeof flags !== 'object' || flags === null) {\n\t\t\tthrow new TypeError('flags must be a non-null object');\n\t\t}\n\n\t\tconst entries = Object.entries(flags) as [string, Flags[keyof Flags]][];\n\t\tif (entries.length === 0) {\n\t\t\tthrow new TypeError('flags must be a non-empty object');\n\t\t}\n\n\t\tconst type = typeof entries[0][1];\n\t\tif (type !== 'number' && type !== 'bigint') {\n\t\t\tthrow new TypeError('A bitfield can only use numbers or bigints for its values');\n\t\t}\n\n\t\tthis.type = type as any;\n\t\tthis.flags = flags;\n\n\t\tif (type === 'number') {\n\t\t\tthis.zero = 0 as any;\n\n\t\t\tlet mask = 0;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'number') throw new TypeError(`The property \"${key}\" does not resolve to a number`);\n\t\t\t\tif (value !== (value | 0)) throw new RangeError(`The property \"${key}\" does not resolve to a safe bitfield value`);\n\t\t\t\tif (value <= 0) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t} else {\n\t\t\tthis.zero = 0n as any;\n\n\t\t\tlet mask = 0n;\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (typeof value !== 'bigint') throw new TypeError(`The property \"${key}\" does not resolve to a bigint`);\n\t\t\t\tif (value <= 0n) throw new RangeError(`The property \"${key}\" resolves to a non-positive value`);\n\t\t\t\tmask |= value;\n\t\t\t}\n\n\t\t\tthis.mask = mask as any;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves a:\n\t * - `string`: If it's a property of {@link Flags}.\n\t * - `number`: If the BitField processes `number` primitives.\n\t * - `bigint`: If the BitField processes `bigint` primitives.\n\t * - `Array`: Resolves recursively.\n\t * @param resolvable The value to resolve.\n\t * @returns The resolved value.\n\t */\n\tpublic resolve(resolvable: ValueResolvable<this>): ValueType<this> {\n\t\tswitch (typeof resolvable) {\n\t\t\tcase 'string':\n\t\t\t\tif ((resolvable as string) in this.flags) return this.flags[resolvable as keyof Flags] as any;\n\t\t\t\tthrow new RangeError('Received a name that could not be resolved to a property of flags');\n\t\t\tcase this.type:\n\t\t\t\treturn ((resolvable as ValueType<this>) & this.mask) as any;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(resolvable)) return resolvable.reduce((acc, value) => this.resolve(value) | acc, this.zero);\n\t\t\t\tthrow new TypeError('Received an object value that is not an Array');\n\t\t\tdefault:\n\t\t\t\tthrow new TypeError(`Received a value that is not either type \"string\", type \"${this.type}\", or an Array`);\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether or not `field` contains any of the bits from `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` has any of `bits`'s bits, also denoted as `A β© B β β
`.\n\t */\n\tpublic any(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\treturn (this.resolve(field) & this.resolve(bits)) !== this.zero;\n\t}\n\n\t/**\n\t * Checks whether or not `field` is a superset of or equal to `bits`.\n\t * @param field The bits to compare the bits from.\n\t * @param bits The bits to compare with.\n\t * @returns Whether or not `field` is a superset of or equal to `bits`, also denoted as `A β B`.\n\t */\n\tpublic has(field: ValueResolvable<this>, bits: ValueResolvable<this>): boolean {\n\t\tconst resolved = this.resolve(bits);\n\t\treturn (this.resolve(field) & resolved) === resolved;\n\t}\n\n\t/**\n\t * Makes the complement of `field`, which is a field of all bits (of `U` or the union of all {@link Flags} bits)\n\t * that do not belong to `A`. It is the result of `U β A`, or `difference(U, field)`.\n\t * @param field The bits to get the complement of.\n\t * @returns The complement of `field`, also denoted `AαΆ` or `A'`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.complement(0b0100);\n\t * // 0b1011\n\t * ```\n\t */\n\tpublic complement(field: ValueResolvable<this>): ValueType<this> {\n\t\treturn this.difference(this.mask, field);\n\t}\n\n\t/**\n\t * Makes a union of all the bits.\n\t * @param fields The bits to create a union of.\n\t * @returns The result of combining all bits together, also denoted as `β
β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.union(0b0001, 0b0100);\n\t * // 0b0101\n\t *\n\t * bitfield.union(0b1100, 0b0001, 0b0010);\n\t * // 0b1111\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Union_(set_theory)}\n\t */\n\tpublic union(...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.zero as ValueType<this>;\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field | this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Makes an intersection of all the bits.\n\t * @param bitfield The first field.\n\t * @param fields The bits to intersect with `bitfield`.\n\t * @returns The result of intersecting `bitfield` with all of the `fields`, also denoted as `A β fields`.\n\t * @example\n\t * ```typescript\n\t * bitfield.intersection(0b0001, 0b0100);\n\t * // 0b0000\n\t *\n\t * bitfield.intersection(0b1100, 0b0100);\n\t * // 0b0100\n\t *\n\t * bitfield.intersection(0b1101, 0b0101, 0b1100);\n\t * // 0b0100\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Intersection_(set_theory)}\n\t */\n\tpublic intersection(bitfield: ValueResolvable<this>, ...fields: readonly ValueResolvable<this>[]): ValueType<this> {\n\t\tlet field = this.resolve(bitfield);\n\t\tfor (const resolvable of fields) {\n\t\t\tfield = (field & this.resolve(resolvable)) as ValueType<this>;\n\t\t}\n\n\t\treturn field;\n\t}\n\n\t/**\n\t * Removes from `a` the bits that exist in `b`.\n\t * @param a The first field.\n\t * @param b The bits to remove from `a`.\n\t * @returns The result of `a β b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.difference(0b1100, 0b0100);\n\t * // 0b1000\n\t *\n\t * bitfield.difference(0b1111, 0b0110);\n\t * // 0b1001\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Difference_(set_theory)}\n\t */\n\tpublic difference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) & ~this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Computes the symmetric difference, denoted as `A β B` or `A Ξ B`, which is the disjunctive union, or the set of\n\t * elements which are in either of the sets, but not in their intersection. As such, this is the result of\n\t * `(A β B) βͺ (B β A)`, `union(difference(a, b), difference(b, a))`, or `a β b`.\n\t * @remarks The empty set (`β
`) is neutral, as such, `A Ξ β
= A` and `A Ξ A = β
`\n\t * @param a The first field.\n\t * @param b The second field.\n\t * @returns The result of computing `a Ξ b`.\n\t * @example\n\t * ```typescript\n\t * bitfield.symmetricDifference(0b1100, 0b0011);\n\t * // 0b1111\n\t *\n\t * bitfield.symmetricDifference(0b1101, 0b1011);\n\t * // 0b0110\n\t * ```\n\t * @seealso {@link https://en.wikipedia.org/wiki/Symmetric_difference}\n\t */\n\tpublic symmetricDifference(a: ValueResolvable<this>, b: ValueResolvable<this>): ValueType<this> {\n\t\treturn (this.resolve(a) ^ this.resolve(b)) as ValueType<this>;\n\t}\n\n\t/**\n\t * Retrieves an array of the properties from {@link Flags} whose values are contained in `field`.\n\t * @param field The field to convert to an array.\n\t * @returns The names of the {@link BitField}'s flag properties whose value are contained in `field`.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toArray(0b0101);\n\t * // ['Read', 'Edit']\n\t * ```\n\t */\n\tpublic toArray(field: ValueResolvable<this>): (keyof Flags)[] {\n\t\tconst bits = this.resolve(field);\n\t\tconst keys: (keyof Flags)[] = [];\n\t\tfor (const [key, bit] of Object.entries(this.flags)) {\n\t\t\t// Inline `.has` code for lower overhead:\n\t\t\tif ((bits & bit) === bit) keys.push(key);\n\t\t}\n\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Retrieves an object with the properties from {@link Flags} whose values are boolean denoting whether or not the\n\t * flag's bit is contained in `field`.\n\t * @param field The field to convert to an object.\n\t * @returns An object with the properties of {@link Flags} which values are boolean.\n\t * @example\n\t * ```typescript\n\t * const bitfield = new BitField({\n\t * \tRead: 0b0001,\n\t * \tWrite: 0b0010,\n\t * \tEdit: 0b0100,\n\t * \tDelete: 0b1000\n\t * });\n\t *\n\t * bitfield.toObject(0b0101);\n\t * // {\n\t * // \tRead: true,\n\t * // \tWrite: false,\n\t * // \tEdit: true,\n\t * // \tDelete: false\n\t * // }\n\t * ```\n\t */\n\tpublic toObject(field: ValueResolvable<this>): Record<keyof Flags, boolean> {\n\t\tconst bits = this.resolve(field);\n\t\treturn Object.fromEntries(Object.entries(this.flags).map(([key, bit]) => [key, (bits & bit) === bit])) as Record<keyof Flags, boolean>;\n\t}\n}\n\ntype PrimitiveType<T> = T extends number ? number : bigint;\ntype MaybeArray<T> = T | readonly T[];\n\n/**\n * Resolves the type of the values the specified {@link BitField} takes.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;\n\n/**\n * Resolves the possible types accepted by the specified {@link BitField}.\n * @typeparam A {@link BitField} instance type.\n */\nexport type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sapphire/bitfield",
|
|
3
|
-
"version": "1.0.0",
|
|
3
|
+
"version": "1.0.1-next.009d3d2.0",
|
|
4
4
|
"description": "A bitfield utility library for JavaScript.",
|
|
5
5
|
"author": "@sapphire",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"access": "public"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@favware/cliff-jumper": "^
|
|
61
|
-
"@vitest/coverage-c8": "^0.
|
|
62
|
-
"tsup": "^6.
|
|
63
|
-
"typedoc": "^0.23.
|
|
64
|
-
"typedoc-json-parser": "^
|
|
65
|
-
"typescript": "^4.
|
|
66
|
-
"vitest": "^0.
|
|
60
|
+
"@favware/cliff-jumper": "^2.0.0",
|
|
61
|
+
"@vitest/coverage-c8": "^0.29.2",
|
|
62
|
+
"tsup": "^6.6.3",
|
|
63
|
+
"typedoc": "^0.23.26",
|
|
64
|
+
"typedoc-json-parser": "^7.2.0",
|
|
65
|
+
"typescript": "^4.9.5",
|
|
66
|
+
"vitest": "^0.29.2"
|
|
67
67
|
}
|
|
68
68
|
}
|