@e280/stz 0.2.10 → 0.2.12
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 +108 -83
- package/package.json +2 -2
- package/s/data/base-x-codecs.ts +11 -0
- package/s/data/base-x.ts +2 -2
- package/s/data/bytename/bytename.test.ts +16 -16
- package/s/data/bytename/bytename.ts +19 -16
- package/s/data/bytename/thumbprint.test.ts +25 -25
- package/s/data/bytename/thumbprint.ts +54 -37
- package/s/data/bytes.ts +4 -1
- package/s/data/data.test.ts +19 -17
- package/s/data/{base58.ts → legacy/base58.ts} +3 -2
- package/s/data/{base64.ts → legacy/base64.ts} +3 -2
- package/s/data/{base64url.ts → legacy/base64url.ts} +3 -2
- package/s/data/{hex.ts → legacy/hex.ts} +3 -2
- package/s/data/nomen/grammar.ts +2 -2
- package/s/data/nomen/nomen.ts +2 -2
- package/s/data/txt.ts +6 -3
- package/s/deep/{parts/equal.test.ts → equal.test.ts} +33 -33
- package/s/deep/{parts/equal.ts → equal.ts} +2 -2
- package/s/deep/{parts/freeze.ts → freeze.ts} +2 -3
- package/s/deep/index.barrel.ts +5 -0
- package/s/deep/index.test.ts +10 -0
- package/s/deep/index.ts +3 -0
- package/s/g/map.ts +36 -0
- package/s/g/pool.ts +24 -0
- package/s/{set-g.ts → g/set.ts} +4 -1
- package/s/g/weak-map.ts +32 -0
- package/s/index.ts +15 -8
- package/s/pubsub.ts +1 -1
- package/s/tests.test.ts +5 -9
- package/s/time.ts +15 -12
- package/s/toq/index.ts +3 -0
- package/s/toq/toq.test.ts +46 -0
- package/s/toq/toq.ts +62 -0
- package/x/data/base-x-codecs.d.ts +8 -0
- package/x/data/base-x-codecs.js +9 -0
- package/x/data/base-x-codecs.js.map +1 -0
- package/x/data/base-x.js +2 -2
- package/x/data/bytename/bytename.d.ts +13 -4
- package/x/data/bytename/bytename.js +16 -14
- package/x/data/bytename/bytename.js.map +1 -1
- package/x/data/bytename/bytename.test.js +16 -16
- package/x/data/bytename/bytename.test.js.map +1 -1
- package/x/data/bytename/thumbprint.d.ts +32 -11
- package/x/data/bytename/thumbprint.js +44 -35
- package/x/data/bytename/thumbprint.js.map +1 -1
- package/x/data/bytename/thumbprint.test.js +25 -25
- package/x/data/bytename/thumbprint.test.js.map +1 -1
- package/x/data/bytes.d.ts +5 -0
- package/x/data/bytes.js +3 -1
- package/x/data/bytes.js.map +1 -1
- package/x/data/data.test.d.ts +37 -0
- package/x/data/data.test.js +18 -17
- package/x/data/data.test.js.map +1 -1
- package/x/data/{base58.d.ts → legacy/base58.d.ts} +1 -0
- package/x/data/{base58.js → legacy/base58.js} +3 -2
- package/x/data/legacy/base58.js.map +1 -0
- package/x/data/{base64.d.ts → legacy/base64.d.ts} +1 -0
- package/x/data/{base64.js → legacy/base64.js} +3 -2
- package/x/data/legacy/base64.js.map +1 -0
- package/x/data/{base64url.d.ts → legacy/base64url.d.ts} +1 -0
- package/x/data/{base64url.js → legacy/base64url.js} +3 -2
- package/x/data/legacy/base64url.js.map +1 -0
- package/x/data/{hex.d.ts → legacy/hex.d.ts} +1 -0
- package/x/data/{hex.js → legacy/hex.js} +3 -2
- package/x/data/legacy/hex.js.map +1 -0
- package/x/data/nomen/grammar.js +2 -2
- package/x/data/nomen/nomen.js +2 -2
- package/x/data/txt.d.ts +9 -0
- package/x/data/txt.js +5 -3
- package/x/data/txt.js.map +1 -1
- package/x/deep/clone.js.map +1 -0
- package/x/deep/clone.test.js.map +1 -0
- package/x/deep/equal.d.ts +1 -0
- package/x/deep/{parts/equal.js → equal.js} +2 -2
- package/x/deep/equal.js.map +1 -0
- package/x/deep/{parts/equal.test.js → equal.test.js} +33 -33
- package/x/deep/equal.test.js.map +1 -0
- package/x/deep/freeze.d.ts +1 -0
- package/x/deep/{parts/freeze.js → freeze.js} +2 -2
- package/x/deep/freeze.js.map +1 -0
- package/x/deep/index.barrel.d.ts +3 -0
- package/x/deep/index.barrel.js +4 -0
- package/x/deep/index.barrel.js.map +1 -0
- package/x/deep/index.d.ts +1 -0
- package/x/deep/index.js +2 -0
- package/x/deep/index.js.map +1 -0
- package/x/deep/{deep.test.d.ts → index.test.d.ts} +15 -1
- package/x/deep/index.test.js +8 -0
- package/x/deep/index.test.js.map +1 -0
- package/x/g/map.d.ts +10 -0
- package/x/g/map.js +30 -0
- package/x/g/map.js.map +1 -0
- package/x/g/pool.d.ts +12 -0
- package/x/g/pool.js +17 -0
- package/x/g/pool.js.map +1 -0
- package/x/{set-g.d.ts → g/set.d.ts} +3 -1
- package/x/{set-g.js → g/set.js} +4 -2
- package/x/g/set.js.map +1 -0
- package/x/g/weak-map.d.ts +9 -0
- package/x/g/weak-map.js +27 -0
- package/x/g/weak-map.js.map +1 -0
- package/x/index.d.ts +13 -8
- package/x/index.js +13 -8
- package/x/index.js.map +1 -1
- package/x/pubsub.d.ts +1 -1
- package/x/tests.test.js +5 -9
- package/x/tests.test.js.map +1 -1
- package/x/time.d.ts +19 -0
- package/x/time.js +14 -12
- package/x/time.js.map +1 -1
- package/x/toq/index.d.ts +1 -0
- package/x/toq/index.js +2 -0
- package/x/toq/index.js.map +1 -0
- package/x/toq/toq.d.ts +4 -0
- package/x/toq/toq.js +48 -0
- package/x/toq/toq.js.map +1 -0
- package/x/toq/toq.test.d.ts +9 -0
- package/x/toq/toq.test.js +40 -0
- package/x/toq/toq.test.js.map +1 -0
- package/s/data/bytename/index.ts +0 -4
- package/s/deep/deep.test.ts +0 -8
- package/s/deep/deep.ts +0 -11
- package/s/map-g.ts +0 -79
- package/x/clone/clone.js.map +0 -1
- package/x/clone/clone.test.js.map +0 -1
- package/x/data/base58.js.map +0 -1
- package/x/data/base64.js.map +0 -1
- package/x/data/base64url.js.map +0 -1
- package/x/data/bytename/index.d.ts +0 -2
- package/x/data/bytename/index.js +0 -3
- package/x/data/bytename/index.js.map +0 -1
- package/x/data/hex.js.map +0 -1
- package/x/deep/deep.d.ts +0 -7
- package/x/deep/deep.js +0 -9
- package/x/deep/deep.js.map +0 -1
- package/x/deep/deep.test.js +0 -6
- package/x/deep/deep.test.js.map +0 -1
- package/x/deep/parts/equal.d.ts +0 -1
- package/x/deep/parts/equal.js.map +0 -1
- package/x/deep/parts/equal.test.js.map +0 -1
- package/x/deep/parts/freeze.d.ts +0 -1
- package/x/deep/parts/freeze.js.map +0 -1
- package/x/map-g.d.ts +0 -24
- package/x/map-g.js +0 -65
- package/x/map-g.js.map +0 -1
- package/x/set-g.js.map +0 -1
- /package/s/{clone → deep}/clone.test.ts +0 -0
- /package/s/{clone → deep}/clone.ts +0 -0
- /package/x/{clone → deep}/clone.d.ts +0 -0
- /package/x/{clone → deep}/clone.js +0 -0
- /package/x/{clone → deep}/clone.test.d.ts +0 -0
- /package/x/{clone → deep}/clone.test.js +0 -0
- /package/x/deep/{parts/equal.test.d.ts → equal.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -111,10 +111,12 @@ await nap(900)
|
|
|
111
111
|
// wait for 900 milliseconds
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
### 🍏
|
|
115
|
-
> extended js
|
|
114
|
+
### 🍏 G Crew
|
|
115
|
+
> extended js data types
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
#### GMap
|
|
118
|
+
> extended js Map
|
|
119
|
+
- many are saying it's *"The Deluxe Mapping Experience"*
|
|
118
120
|
```ts
|
|
119
121
|
import {MapG} from "@e280/stz"
|
|
120
122
|
|
|
@@ -134,13 +136,13 @@ await nap(900)
|
|
|
134
136
|
// "rofl"
|
|
135
137
|
```
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
#### GSet
|
|
138
140
|
> extended js Set
|
|
139
141
|
- `new SetG<T>()`
|
|
140
142
|
- `set.adds(item1, item2, item3)` — add multiple items without a for-loop
|
|
141
143
|
- `set.deletes(item1, item2, item3)` — add multiple items without a for-loop
|
|
142
144
|
|
|
143
|
-
|
|
145
|
+
#### GWeakMap
|
|
144
146
|
> extended js WeakMap
|
|
145
147
|
- `new WeakMapG<K, V>()`
|
|
146
148
|
- `weakMap.require(key)` — returns value for key.. if missing, throw an error
|
|
@@ -218,15 +220,15 @@ fn()
|
|
|
218
220
|
// coolAction is only called once here, other calls are redundant
|
|
219
221
|
```
|
|
220
222
|
|
|
221
|
-
### 🍏 `
|
|
223
|
+
### 🍏 `cycle(fn)`
|
|
222
224
|
> execute a function over and over again, back to back
|
|
223
225
|
|
|
224
226
|
```ts
|
|
225
|
-
import {
|
|
227
|
+
import {cycle} from "@e280/stz"
|
|
226
228
|
|
|
227
229
|
let ticks = 0
|
|
228
230
|
|
|
229
|
-
const stop =
|
|
231
|
+
const stop = cycle(async() => {
|
|
230
232
|
|
|
231
233
|
// use a nap to add a delay between each execution
|
|
232
234
|
await nap(200)
|
|
@@ -244,78 +246,49 @@ stop()
|
|
|
244
246
|
|
|
245
247
|
## 🥨 stz data utilities
|
|
246
248
|
|
|
247
|
-
### 🍏
|
|
248
|
-
> convert to/from hexadecimal string format
|
|
249
|
-
- `Hex.fromBytes(bytes)` — bytes to hex string
|
|
250
|
-
- `Hex.toBytes(string)` — hex string to bytes
|
|
251
|
-
- `Hex.random(32)` — generate random hex string (32 bytes)
|
|
252
|
-
|
|
253
|
-
### 🍏 Base64
|
|
254
|
-
> convert to/from base64 string format
|
|
255
|
-
- `Base64.fromBytes(bytes)` — bytes to string
|
|
256
|
-
- `Base64.toBytes(string)` — string to bytes
|
|
257
|
-
- `Base64.random(32)` — generate random string (32 bytes)
|
|
258
|
-
|
|
259
|
-
### 🍏 Base64url
|
|
260
|
-
> convert to/from base64 string format
|
|
261
|
-
- `Base64url.fromBytes(bytes)` — bytes to string
|
|
262
|
-
- `Base64url.toBytes(string)` — string to bytes
|
|
263
|
-
- `Base64url.random(32)` — generate random string (32 bytes)
|
|
264
|
-
|
|
265
|
-
### 🍏 Base58
|
|
266
|
-
> convert to/from base64 string format
|
|
267
|
-
- `Base58.fromBytes(bytes)` — bytes to string
|
|
268
|
-
- `Base58.toBytes(string)` — string to bytes
|
|
269
|
-
- `Base58.random(32)` — generate random string (32 bytes)
|
|
270
|
-
|
|
271
|
-
### 🍏 Txt
|
|
249
|
+
### 🍏 txt
|
|
272
250
|
> convert to/from utf8 string format
|
|
273
|
-
- `
|
|
274
|
-
- `
|
|
251
|
+
- `txt.fromBytes(bytes)` — bytes to string
|
|
252
|
+
- `txt.toBytes(string)` — string to bytes
|
|
275
253
|
|
|
276
|
-
### 🍏
|
|
254
|
+
### 🍏 bytes
|
|
277
255
|
> utilities for dealing with Uint8Array
|
|
278
|
-
- `
|
|
279
|
-
- `
|
|
256
|
+
- `bytes.eq(bytesA, bytesB)` — check if two byte arrays are equal
|
|
257
|
+
- `bytes.random(32)` — generate crypto-random bytes
|
|
280
258
|
|
|
281
|
-
### 🍏 BaseX
|
|
282
|
-
> convert data
|
|
283
|
-
- make a BaseX instance
|
|
284
|
-
```ts
|
|
285
|
-
import {BaseX} from "@e280/stz"
|
|
259
|
+
### 🍏 BaseX utilities
|
|
260
|
+
> convert binary data to/from various encodings
|
|
286
261
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
```ts
|
|
291
|
-
hex.toBytes("9960cd633a46acfe8307d8a400e842da0d930a75fb8188e0f5da264e4b6b4e5b")
|
|
292
|
-
// Uint8Array
|
|
262
|
+
```ts
|
|
263
|
+
import {hex, base58, base64} from "@e280/stz"
|
|
264
|
+
```
|
|
293
265
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
266
|
+
#### hex
|
|
267
|
+
> all BaseX utilities have these methods
|
|
268
|
+
- `hex.fromBytes(u8array)` — encode bytes to string
|
|
269
|
+
- `hex.toBytes(str)` — decode string to bytes
|
|
270
|
+
- `hex.toInteger(string)` — decode string as js integer
|
|
271
|
+
- `hex.fromInteger(n)` — encode js integer as a string
|
|
272
|
+
- `hex.random(32)` — generate random encoded string (32 bytes)
|
|
273
|
+
|
|
274
|
+
#### all BaseX utilities
|
|
275
|
+
- `hex`
|
|
276
|
+
- `base2`
|
|
277
|
+
- `base36`
|
|
278
|
+
- `base58`
|
|
279
|
+
- `base62`
|
|
280
|
+
- `base64`
|
|
281
|
+
- `base64url`
|
|
282
|
+
|
|
283
|
+
#### make a custom BaseX utility
|
|
284
|
+
- you can provide a `lexicon` to produce your own BaseX codec
|
|
285
|
+
```ts
|
|
286
|
+
const myHex = new BaseX({characters: "0123456789abcdef"})
|
|
287
|
+
```
|
|
301
288
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
```
|
|
305
|
-
- available lexicons include
|
|
306
|
-
- base2
|
|
307
|
-
- hex
|
|
308
|
-
- base36
|
|
309
|
-
- base58
|
|
310
|
-
- base62
|
|
311
|
-
- base64 (with standard padding)
|
|
312
|
-
- base64url
|
|
313
|
-
- you can make insanely compact timestamps like this:
|
|
289
|
+
#### tiny timestamps
|
|
290
|
+
- fun fact: you can make insanely compact timestamp strings like this:
|
|
314
291
|
```ts
|
|
315
|
-
import {BaseX} from "@e280/stz"
|
|
316
|
-
|
|
317
|
-
const base62 = new BaseX(BaseX.lexicons.base62)
|
|
318
|
-
|
|
319
292
|
base62.fromInteger(Date.now() / 1000)
|
|
320
293
|
// "1uK3au"
|
|
321
294
|
```
|
|
@@ -323,35 +296,31 @@ stop()
|
|
|
323
296
|
- `1uK3au` base62 epoch seconds (6 chars)
|
|
324
297
|
- *nice*
|
|
325
298
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<br/>
|
|
329
|
-
|
|
330
|
-
### 🍏 Bytename
|
|
299
|
+
### 🍏 bytename
|
|
331
300
|
> friendly string encoding for binary data
|
|
332
301
|
|
|
333
302
|
a bytename looks like `"midsen.picmyn.widrep.baclut dotreg.filtyp.nosnus.siptev"`. that's 16 bytes. each byte maps to a three-letter triplet
|
|
334
303
|
|
|
335
|
-
the bytename parser (`
|
|
304
|
+
the bytename parser (`bytename.toBytes`) ignores all non-alphabetic characters. thus `midsen.picmyn`, `midsenpicmyn`, and `mid@sen$pic@myn` are all equal.
|
|
336
305
|
|
|
337
306
|
```ts
|
|
338
|
-
import {
|
|
307
|
+
import {bytename} from "@e280/stz"
|
|
339
308
|
```
|
|
340
309
|
- ```ts
|
|
341
|
-
|
|
310
|
+
bytename.fromBytes(new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF]))
|
|
342
311
|
// "ribmug.hilmun"
|
|
343
312
|
```
|
|
344
313
|
- ```ts
|
|
345
|
-
|
|
314
|
+
bytename.toBytes("ribmug.hilmun")
|
|
346
315
|
// Uint8Array, 4 bytes
|
|
347
316
|
```
|
|
348
317
|
- ```ts
|
|
349
|
-
const
|
|
318
|
+
const data = new Uint8Array([
|
|
350
319
|
0xDE, 0xAD, 0xBE, 0xEF,
|
|
351
320
|
0xDE, 0xAD, 0xBE, 0xEF,
|
|
352
321
|
])
|
|
353
322
|
|
|
354
|
-
|
|
323
|
+
bytename.fromBytes(data, {
|
|
355
324
|
groupSize: 2, // default is 4
|
|
356
325
|
groupSeparator: " ",
|
|
357
326
|
wordSeparator: ".",
|
|
@@ -359,6 +328,62 @@ import {Bytename} from "@e280/stz"
|
|
|
359
328
|
// "ribmug.hilmun ribmug.hilmun"
|
|
360
329
|
```
|
|
361
330
|
|
|
331
|
+
### 🍏 thumbprint
|
|
332
|
+
> hybrid of bytename and base58 to make binary data more human-friendly
|
|
333
|
+
- looks like `nodlyn.fasrep.habbud.ralwel.Avo7gFmdWMRHkwsD149mcaBoZdS69iXuJ`
|
|
334
|
+
- the idea is that the first parts are in bytename format, so it's easy for humans to recognize
|
|
335
|
+
- and the remaining data is shown in base58
|
|
336
|
+
- `thumbprint.fromBytes(u8array)` — encode bytes to thumbprint string
|
|
337
|
+
- `thumbprint.toBytes(thumbstring)` — decode thumbprint string to bytes
|
|
338
|
+
- `thumbprint.fromHex(hexstring)` — convert a hex string into a thumbprint
|
|
339
|
+
- `thumbprint.toHex(thumbstring)` — convert a thumbprint into a hex string
|
|
340
|
+
|
|
341
|
+
### 🍏 toq
|
|
342
|
+
> tar-like binary file format for efficiently packing multiple files together
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
import {toq, txt} from "@e280/stz"
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### data layout
|
|
349
|
+
- 4 magic bytes `"TOQ\x01"`
|
|
350
|
+
- for each file (little endian)
|
|
351
|
+
- `name length` 1 byte (u8)
|
|
352
|
+
- `name` x bytes (max 255 B)
|
|
353
|
+
- `data length` 4 bytes (u32)
|
|
354
|
+
- `data` x bytes (max 4 GB)
|
|
355
|
+
|
|
356
|
+
#### toq pack/unpack
|
|
357
|
+
- **toq.pack** — accepts any iterable of file entries
|
|
358
|
+
```ts
|
|
359
|
+
const pack: Uint8Array = toq.pack([
|
|
360
|
+
["hello.txt", txt.toBytes("hello world")],
|
|
361
|
+
["deadbeef.data", new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF])],
|
|
362
|
+
])
|
|
363
|
+
```
|
|
364
|
+
- **toq.is** — check if a file is a toq pack or not
|
|
365
|
+
```ts
|
|
366
|
+
toq.is(pack) // true
|
|
367
|
+
```
|
|
368
|
+
- **toq.unpack** — generator fn yields file entries
|
|
369
|
+
```ts
|
|
370
|
+
for (const [name, data] of toq.unpack(pack))
|
|
371
|
+
console.log(name, data.length)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### toq works nice with maps
|
|
375
|
+
- **pack a map of files**
|
|
376
|
+
```ts
|
|
377
|
+
const files = new Map<string, Uint8Array>()
|
|
378
|
+
files.set("hello.txt", txt.toBytes("hello world"))
|
|
379
|
+
files.set("deadbeef.data", new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF]))
|
|
380
|
+
|
|
381
|
+
const pack = toq.pack(files)
|
|
382
|
+
```
|
|
383
|
+
- **unpack into a new map**
|
|
384
|
+
```ts
|
|
385
|
+
const files = new Map(toq.unpack(pack))
|
|
386
|
+
```
|
|
362
387
|
|
|
363
388
|
|
|
364
389
|
<br/><br/>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e280/stz",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "everyday ts fns for everything",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chase Moskal <chasemoskal@gmail.com>",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@e280/science": "^0.1.2",
|
|
31
|
-
"@types/node": "^24.
|
|
31
|
+
"@types/node": "^24.7.1",
|
|
32
32
|
"npm-run-all": "^4.1.5",
|
|
33
33
|
"typescript": "^5.9.3"
|
|
34
34
|
},
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
import {BaseX} from "./base-x.js"
|
|
3
|
+
|
|
4
|
+
export const hex = new BaseX(BaseX.lexicons.hex)
|
|
5
|
+
export const base2 = new BaseX(BaseX.lexicons.base2)
|
|
6
|
+
export const base36 = new BaseX(BaseX.lexicons.base36)
|
|
7
|
+
export const base58 = new BaseX(BaseX.lexicons.base58)
|
|
8
|
+
export const base62 = new BaseX(BaseX.lexicons.base62)
|
|
9
|
+
export const base64 = new BaseX(BaseX.lexicons.base64)
|
|
10
|
+
export const base64url = new BaseX(BaseX.lexicons.base64url)
|
|
11
|
+
|
package/s/data/base-x.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import {bytes} from "./bytes.js"
|
|
3
3
|
|
|
4
4
|
export type Lexicon = {
|
|
5
5
|
characters: string
|
|
@@ -164,7 +164,7 @@ export class BaseX {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
random(count = 32) {
|
|
167
|
-
return this.fromBytes(
|
|
167
|
+
return this.fromBytes(bytes.random(count))
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import {bytes} from "../bytes.js"
|
|
3
|
+
import {bytename} from "./bytename.js"
|
|
4
4
|
import {Science, test, expect} from "@e280/science"
|
|
5
5
|
|
|
6
6
|
const deadbeef = new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF])
|
|
7
7
|
|
|
8
|
-
function good(
|
|
9
|
-
expect(
|
|
8
|
+
function good(b: Uint8Array) {
|
|
9
|
+
expect(bytes.eq(b, deadbeef)).ok()
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export default Science.suite({
|
|
13
13
|
"bytes->string->bytes": test(async() => {
|
|
14
|
-
const text =
|
|
14
|
+
const text = bytename.fromBytes(deadbeef)
|
|
15
15
|
expect(text).is("ribmug.hilmun")
|
|
16
|
-
good(
|
|
16
|
+
good(bytename.toBytes(text))
|
|
17
17
|
}),
|
|
18
18
|
|
|
19
19
|
"zero bytes": test(async() => {
|
|
20
|
-
const text =
|
|
20
|
+
const text = bytename.fromBytes(new Uint8Array([]))
|
|
21
21
|
expect(text).is("")
|
|
22
22
|
}),
|
|
23
23
|
|
|
24
24
|
"one byte": test(async() => {
|
|
25
|
-
const text =
|
|
25
|
+
const text = bytename.fromBytes(new Uint8Array([0x00]))
|
|
26
26
|
expect(text).is("doz")
|
|
27
27
|
}),
|
|
28
28
|
|
|
29
29
|
"groupings": test(async() => {
|
|
30
30
|
const bytes = new Uint8Array([...deadbeef, ...deadbeef])
|
|
31
|
-
const text =
|
|
31
|
+
const text = bytename.fromBytes(bytes, {
|
|
32
32
|
groupSize: 2,
|
|
33
33
|
groupSeparator: " ",
|
|
34
34
|
wordSeparator: ".",
|
|
@@ -37,13 +37,13 @@ export default Science.suite({
|
|
|
37
37
|
}),
|
|
38
38
|
|
|
39
39
|
"wordsep": Science.suite({
|
|
40
|
-
"underscore": test(async() => good(
|
|
41
|
-
"uppercase": test(async() => good(
|
|
42
|
-
"dots": test(async() => good(
|
|
43
|
-
"crushed": test(async() => good(
|
|
44
|
-
"space": test(async() => good(
|
|
45
|
-
"spaces": test(async() => good(
|
|
46
|
-
"whitespace": test(async() => good(
|
|
40
|
+
"underscore": test(async() => good(bytename.toBytes("ribmug_hilmun"))),
|
|
41
|
+
"uppercase": test(async() => good(bytename.toBytes("RIBMUG_HILMUN"))),
|
|
42
|
+
"dots": test(async() => good(bytename.toBytes("ribmug.hilmun"))),
|
|
43
|
+
"crushed": test(async() => good(bytename.toBytes("ribmughilmun"))),
|
|
44
|
+
"space": test(async() => good(bytename.toBytes("ribmug hilmun"))),
|
|
45
|
+
"spaces": test(async() => good(bytename.toBytes("ribmug hilmun"))),
|
|
46
|
+
"whitespace": test(async() => good(bytename.toBytes("\n ribmug \n \t \n hilmun \n"))),
|
|
47
47
|
}),
|
|
48
48
|
})
|
|
49
49
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import {bytes} from "../bytes.js"
|
|
3
|
+
import {hex} from "../base-x-codecs.js"
|
|
4
4
|
import {prefixes} from "./utils/prefixes.js"
|
|
5
5
|
import {suffixes} from "./utils/suffixes.js"
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ export type BytenameOptions = {
|
|
|
16
16
|
* - each byte maps to a three-letter triplet
|
|
17
17
|
* - all delimiters are just sugar, parser doesn't care
|
|
18
18
|
*/
|
|
19
|
-
export const
|
|
19
|
+
export const bytename = {
|
|
20
20
|
defaults: (<BytenameOptions>{
|
|
21
21
|
groupSize: 4,
|
|
22
22
|
wordSeparator: ".",
|
|
@@ -24,21 +24,21 @@ export const Bytename = {
|
|
|
24
24
|
}),
|
|
25
25
|
|
|
26
26
|
random(byteCount: number, options?: Partial<BytenameOptions>) {
|
|
27
|
-
const
|
|
28
|
-
return this.fromBytes(
|
|
27
|
+
const b = bytes.random(byteCount)
|
|
28
|
+
return this.fromBytes(b, options)
|
|
29
29
|
},
|
|
30
30
|
|
|
31
|
-
fromBytes(
|
|
31
|
+
fromBytes(b: Uint8Array, options: Partial<BytenameOptions> = {}) {
|
|
32
32
|
const {
|
|
33
|
-
groupSize =
|
|
34
|
-
wordSeparator =
|
|
35
|
-
groupSeparator =
|
|
33
|
+
groupSize = bytename.defaults.groupSize,
|
|
34
|
+
wordSeparator = bytename.defaults.wordSeparator,
|
|
35
|
+
groupSeparator = bytename.defaults.groupSeparator,
|
|
36
36
|
} = options
|
|
37
37
|
|
|
38
38
|
const words: string[] = []
|
|
39
39
|
let currentWord: string[] = []
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
b.forEach((byte, index) => {
|
|
42
42
|
const source = ((index % 2) === 0) ? prefixes : suffixes
|
|
43
43
|
currentWord.push(source[byte]!)
|
|
44
44
|
if (currentWord.length === 2) {
|
|
@@ -57,8 +57,8 @@ export const Bytename = {
|
|
|
57
57
|
return grouped.join(groupSeparator)
|
|
58
58
|
},
|
|
59
59
|
|
|
60
|
-
toBytes(
|
|
61
|
-
const letters =
|
|
60
|
+
toBytes(bname: string) {
|
|
61
|
+
const letters = bname
|
|
62
62
|
.toLowerCase()
|
|
63
63
|
.replace(/[^a-z]/g, "") // strip everything except letters
|
|
64
64
|
|
|
@@ -79,12 +79,15 @@ export const Bytename = {
|
|
|
79
79
|
}))
|
|
80
80
|
},
|
|
81
81
|
|
|
82
|
-
toHex(
|
|
83
|
-
return
|
|
82
|
+
toHex(bname: string) {
|
|
83
|
+
return hex.fromBytes(bytename.toBytes(bname))
|
|
84
84
|
},
|
|
85
85
|
|
|
86
|
-
fromHex(
|
|
87
|
-
return
|
|
86
|
+
fromHex(h: string, options?: Partial<BytenameOptions>) {
|
|
87
|
+
return bytename.fromBytes(hex.toBytes(h), options)
|
|
88
88
|
},
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/** @deprecated renamed to `bytename` */
|
|
92
|
+
export const Bytename = bytename
|
|
93
|
+
|
|
@@ -1,53 +1,53 @@
|
|
|
1
1
|
|
|
2
2
|
import {Science, test, expect} from "@e280/science"
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import {bytes} from "../bytes.js"
|
|
4
|
+
import {hex} from "../base-x-codecs.js"
|
|
5
|
+
import {thumbprint} from "./thumbprint.js"
|
|
6
6
|
|
|
7
7
|
const sampleThumbprint = "nodlyn.fasrep.habbud.ralwel.Avo7gFmdWMRHkwsD149mcaBoZdS69iXuJ"
|
|
8
8
|
const sampleHex = "88e8c3fad1028fcf6ce5ac491578850f4d833336feca03b608265501c3019d59"
|
|
9
|
-
const sampleBytes =
|
|
9
|
+
const sampleBytes = hex.toBytes(sampleHex)
|
|
10
10
|
|
|
11
|
-
function good(
|
|
12
|
-
expect(
|
|
11
|
+
function good(b: Uint8Array) {
|
|
12
|
+
expect(bytes.eq(b, sampleBytes)).ok()
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export default Science.suite({
|
|
16
16
|
"bytes->string->bytes": test(async() => {
|
|
17
|
-
const text =
|
|
17
|
+
const text = thumbprint.fromBytes(sampleBytes)
|
|
18
18
|
expect(text).is(sampleThumbprint)
|
|
19
|
-
good(
|
|
19
|
+
good(thumbprint.toBytes(text))
|
|
20
20
|
}),
|
|
21
21
|
|
|
22
22
|
"zero bytes": test(async() => {
|
|
23
|
-
const text =
|
|
23
|
+
const text = thumbprint.fromBytes(new Uint8Array([]))
|
|
24
24
|
expect(text).is("")
|
|
25
|
-
expect(
|
|
25
|
+
expect(bytes.eq(thumbprint.toBytes(text), new Uint8Array([]))).ok()
|
|
26
26
|
}),
|
|
27
27
|
|
|
28
28
|
"one byte": test(async() => {
|
|
29
|
-
const text =
|
|
29
|
+
const text = thumbprint.fromBytes(new Uint8Array([0x00]))
|
|
30
30
|
expect(text).is("doz")
|
|
31
|
-
expect(
|
|
31
|
+
expect(bytes.eq(thumbprint.toBytes(text), new Uint8Array([0x00]))).ok()
|
|
32
32
|
}),
|
|
33
33
|
|
|
34
34
|
"partially": Science.suite({
|
|
35
|
-
"normal": test(async() => expect(
|
|
36
|
-
"nothing": test(async() => expect(
|
|
37
|
-
"no-bulk": test(async() => expect(
|
|
38
|
-
"one-byte": test(async() => expect(
|
|
39
|
-
"three-byte": test(async() => expect(
|
|
40
|
-
"one-byte-sigil": test(async() => expect(
|
|
35
|
+
"normal": test(async() => expect(thumbprint.toBytes(sampleThumbprint).length).ok()),
|
|
36
|
+
"nothing": test(async() => expect(thumbprint.toBytes("").length).is(0)),
|
|
37
|
+
"no-bulk": test(async() => expect(thumbprint.toBytes("nodlyn.fasrep").length).ok()),
|
|
38
|
+
"one-byte": test(async() => expect(thumbprint.toBytes("nod").length).is(1)),
|
|
39
|
+
"three-byte": test(async() => expect(thumbprint.toBytes("nodlynfas").length).is(3)),
|
|
40
|
+
"one-byte-sigil": test(async() => expect(thumbprint.toBytes("nod::39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k").length).ok()),
|
|
41
41
|
}),
|
|
42
42
|
|
|
43
43
|
"tolerance": Science.suite({
|
|
44
|
-
"normal": test(async() => good(
|
|
45
|
-
"coolio": test(async() => good(
|
|
46
|
-
"spaces": test(async() => good(
|
|
47
|
-
"dots": test(async() => good(
|
|
48
|
-
"one-space": test(async() => good(
|
|
49
|
-
"one-newline": test(async() => good(
|
|
50
|
-
"whitespace": test(async() => good(
|
|
44
|
+
"normal": test(async() => good(thumbprint.toBytes("nodlyn.fasrep::39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k"))),
|
|
45
|
+
"coolio": test(async() => good(thumbprint.toBytes("nodlyn.fasrep..39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k"))),
|
|
46
|
+
"spaces": test(async() => good(thumbprint.toBytes("nodlyn fasrep 39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k"))),
|
|
47
|
+
"dots": test(async() => good(thumbprint.toBytes("nodlyn.fasrep.39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k"))),
|
|
48
|
+
"one-space": test(async() => good(thumbprint.toBytes("nodlynfasrep 39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k"))),
|
|
49
|
+
"one-newline": test(async() => good(thumbprint.toBytes("nodlynfasrep\n39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k"))),
|
|
50
|
+
"whitespace": test(async() => good(thumbprint.toBytes("\t\n nodlyn\n fasrep \n\n\t\n 39gfeGFAAnBzH5pkT7EdoETMUMAekG9h1iymk6k\n\t"))),
|
|
51
51
|
}),
|
|
52
52
|
})
|
|
53
53
|
|