@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 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
- Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
242
-
243
- <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
244
- <!-- prettier-ignore-start -->
245
- <!-- markdownlint-disable -->
246
- <table>
247
- <tr>
248
- <td align="center"><a href="https://favware.tech/"><img src="https://avatars3.githubusercontent.com/u/4019718?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeroen Claassens</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=favna" title="Code">πŸ’»</a> <a href="#infra-favna" title="Infrastructure (Hosting, Build-Tools, etc)">πŸš‡</a> <a href="#projectManagement-favna" title="Project Management">πŸ“†</a> <a href="https://github.com/sapphiredev/utilities/commits?author=favna" title="Documentation">πŸ“–</a> <a href="https://github.com/sapphiredev/utilities/commits?author=favna" title="Tests">⚠️</a></td>
249
- <td align="center"><a href="https://github.com/kyranet"><img src="https://avatars0.githubusercontent.com/u/24852502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aura RomΓ‘n</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=kyranet" title="Code">πŸ’»</a> <a href="#projectManagement-kyranet" title="Project Management">πŸ“†</a> <a href="https://github.com/sapphiredev/utilities/pulls?q=is%3Apr+reviewed-by%3Akyranet" title="Reviewed Pull Requests">πŸ‘€</a> <a href="https://github.com/sapphiredev/utilities/commits?author=kyranet" title="Tests">⚠️</a></td>
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
- declare type PrimitiveType<T> = T extends number ? number : bigint;
163
- declare type MaybeArray<T> = T | readonly T[];
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
- declare type ValueType<T> = T extends BitField<infer Flags> ? PrimitiveType<Flags[keyof Flags]> : never;
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
- declare type ValueResolvable<T> = T extends BitField<infer Flags> ? MaybeArray<keyof Flags | PrimitiveType<Flags[keyof Flags]>> : never;
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 };
@@ -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
@@ -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":";;;;;;;;;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.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
@@ -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": "^1.8.8",
61
- "@vitest/coverage-c8": "^0.24.3",
62
- "tsup": "^6.2.3",
63
- "typedoc": "^0.23.16",
64
- "typedoc-json-parser": "^6.0.0",
65
- "typescript": "^4.8.4",
66
- "vitest": "^0.24.3"
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
  }