fix: multi-repo local dev (file:../ deps, package exports, missing deps)
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
name: Build Status
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [lts/*]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2022 Mathias Buus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# z32
|
||||
|
||||
z-base-32 encoder & decoder
|
||||
|
||||
```
|
||||
npm install z32
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
``` js
|
||||
const z32 = require('z32')
|
||||
|
||||
const s = z32.encode('Hello, World!')
|
||||
|
||||
console.log(s) // jb1sa5dxfoofq551pt1nn
|
||||
|
||||
const b = z32.decode(s)
|
||||
|
||||
console.log(b) // Buffer('Hello, World!')
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
#### `const s = z32.encode(stringOrBuffer)`
|
||||
|
||||
Encode a string or buffer to z-base-32.
|
||||
|
||||
#### `const buf = z32.decode(s)`
|
||||
|
||||
Returns a decoded buffer. Throws if the string is invalid.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
const bench = require('nanobench')
|
||||
const { randomBytes } = require('node:crypto')
|
||||
|
||||
const buffers = Array(1e4)
|
||||
.fill(null)
|
||||
.map(() => {
|
||||
return randomBytes(Math.round(Math.random() * 100))
|
||||
})
|
||||
|
||||
bench('z32 encode 100 times', function (b) {
|
||||
const z32 = require('.')
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const buf of buffers) {
|
||||
z32.encode(buf)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('z32 decode 100 times', function (b) {
|
||||
const z32 = require('.')
|
||||
const encoded = buffers.map(buf => z32.encode(buf))
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const s of encoded) {
|
||||
z32.decode(s)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench("buf.toString('hex') 100 times", function (b) {
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const buf of buffers) {
|
||||
buf.toString('hex')
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench("Buffer.from(s, 'hex') 100 times", function (b) {
|
||||
const encoded = buffers.map(buf => buf.toString('hex'))
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const s of encoded) {
|
||||
Buffer.from(s, 'hex')
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('base32 encode 100 times', function (b) {
|
||||
const base32 = require('base32')
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const buf of buffers) {
|
||||
base32.encode(buf)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('base32 decode 100 times', function (b) {
|
||||
const base32 = require('base32')
|
||||
const encoded = buffers.map(buf => base32.encode(buf))
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const s of encoded) {
|
||||
base32.decode(s)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('rfc4648.base32 encode 100 times', function (b) {
|
||||
const { base32 } = require('rfc4648')
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const buf of buffers) {
|
||||
base32.stringify(buf)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('rfc4648.base32 decode 100 times', function (b) {
|
||||
const { base32 } = require('rfc4648')
|
||||
const encoded = buffers.map(buf => base32.stringify(buf))
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const s of encoded) {
|
||||
base32.parse(s, { out: Buffer.allocUnsafe })
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('base-x z-base-32 encode 100 times', function (b) {
|
||||
const ZBASE32 = 'ybndrfg8ejkmcpqxot1uwisza345h769'
|
||||
const base32 = require('base-x')(ZBASE32)
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const buf of buffers) {
|
||||
base32.encode(buf)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
|
||||
bench('base-x z-base-32 decode 100 times', function (b) {
|
||||
const ZBASE32 = 'ybndrfg8ejkmcpqxot1uwisza345h769'
|
||||
const base32 = require('base-x')(ZBASE32)
|
||||
const encoded = buffers.map(buf => base32.encode(buf))
|
||||
b.start()
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (const s of encoded) {
|
||||
base32.decode(s)
|
||||
}
|
||||
}
|
||||
|
||||
b.end()
|
||||
})
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
const b4a = require('b4a')
|
||||
|
||||
const ALPHABET = 'ybndrfg8ejkmcpqxot1uwisza345h769'
|
||||
const MIN = 0x31 // 1
|
||||
const MAX = 0x7a // z
|
||||
const REVERSE = new Int8Array(1 + MAX - MIN)
|
||||
|
||||
REVERSE.fill(-1)
|
||||
|
||||
for (let i = 0; i < ALPHABET.length; i++) {
|
||||
const v = ALPHABET.charCodeAt(i) - MIN
|
||||
REVERSE[v] = i
|
||||
}
|
||||
|
||||
exports.encode = encode
|
||||
exports.decode = decode
|
||||
exports.ALPHABET = ALPHABET
|
||||
|
||||
function decode (s, out) {
|
||||
let pb = 0
|
||||
let ps = 0
|
||||
|
||||
const r = s.length & 7
|
||||
const q = (s.length - r) / 8
|
||||
|
||||
if (!out) out = b4a.allocUnsafe(Math.ceil(s.length * 5 / 8))
|
||||
|
||||
// 0 5 2 7 4 1 6 3 (+5 mod 8)
|
||||
for (let i = 0; i < q; i++) {
|
||||
const a = quintet(s, ps++)
|
||||
const b = quintet(s, ps++)
|
||||
const c = quintet(s, ps++)
|
||||
const d = quintet(s, ps++)
|
||||
const e = quintet(s, ps++)
|
||||
const f = quintet(s, ps++)
|
||||
const g = quintet(s, ps++)
|
||||
const h = quintet(s, ps++)
|
||||
|
||||
out[pb++] = (a << 3) | (b >>> 2)
|
||||
out[pb++] = ((b & 0b11) << 6) | (c << 1) | (d >>> 4)
|
||||
out[pb++] = ((d & 0b1111) << 4) | (e >>> 1)
|
||||
out[pb++] = ((e & 0b1) << 7) | (f << 2) | (g >>> 3)
|
||||
out[pb++] = ((g & 0b111) << 5) | h
|
||||
}
|
||||
|
||||
if (r === 0) return out.subarray(0, pb)
|
||||
|
||||
const a = quintet(s, ps++)
|
||||
const b = quintet(s, ps++)
|
||||
|
||||
out[pb++] = (a << 3) | (b >>> 2)
|
||||
|
||||
if (r <= 2) return out.subarray(0, pb)
|
||||
|
||||
const c = quintet(s, ps++)
|
||||
const d = quintet(s, ps++)
|
||||
|
||||
out[pb++] = ((b & 0b11) << 6) | (c << 1) | (d >>> 4)
|
||||
|
||||
if (r <= 4) return out.subarray(0, pb)
|
||||
|
||||
const e = quintet(s, ps++)
|
||||
|
||||
out[pb++] = ((d & 0b1111) << 4) | (e >>> 1)
|
||||
|
||||
if (r <= 5) return out.subarray(0, pb)
|
||||
|
||||
const f = quintet(s, ps++)
|
||||
const g = quintet(s, ps++)
|
||||
|
||||
out[pb++] = ((e & 0b1) << 7) | (f << 2) | (g >>> 3)
|
||||
|
||||
if (r <= 7) return out.subarray(0, pb)
|
||||
|
||||
const h = quintet(s, ps++)
|
||||
|
||||
out[pb++] = ((g & 0b111) << 5) | h
|
||||
|
||||
return out.subarray(0, pb)
|
||||
}
|
||||
|
||||
function encode (buf) {
|
||||
if (typeof buf === 'string') buf = b4a.from(buf)
|
||||
|
||||
const max = buf.byteLength * 8
|
||||
|
||||
let s = ''
|
||||
|
||||
for (let p = 0; p < max; p += 5) {
|
||||
const i = p >>> 3
|
||||
const j = p & 7
|
||||
|
||||
if (j <= 3) {
|
||||
s += ALPHABET[(buf[i] >>> (3 - j)) & 0b11111]
|
||||
continue
|
||||
}
|
||||
|
||||
const of = j - 3
|
||||
const h = (buf[i] << of) & 0b11111
|
||||
const l = (i >= buf.byteLength ? 0 : buf[i + 1]) >>> (8 - of)
|
||||
|
||||
s += ALPHABET[h | l]
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
function quintet (s, i) {
|
||||
if (i > s.length) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const v = s.charCodeAt(i)
|
||||
|
||||
if (v < MIN || v > MAX) {
|
||||
throw Error('Invalid character in base32 input: "' + s[i] + '" at position ' + i)
|
||||
}
|
||||
|
||||
const bits = REVERSE[v - MIN]
|
||||
|
||||
if (bits === -1) {
|
||||
throw Error('Invalid character in base32 input: "' + s[i] + '" at position ' + i)
|
||||
}
|
||||
|
||||
return bits
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "z32",
|
||||
"version": "1.1.0",
|
||||
"description": "Encode & decode z-base32",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"b4a": "^1.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"base-x": "^4.0.0",
|
||||
"base32": "0.0.7",
|
||||
"brittle": "^3.1.3",
|
||||
"nanobench": "^3.0.0",
|
||||
"rfc4648": "^1.5.2",
|
||||
"standard": "^17.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mafintosh/z32.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard && brittle test.js",
|
||||
"bench": "node benchmark.js"
|
||||
},
|
||||
"author": "Mathias Buus (@mafintosh)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mafintosh/z32/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mafintosh/z32"
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
const z32 = require('./')
|
||||
const b4a = require('b4a')
|
||||
const test = require('brittle')
|
||||
const crypto = require('crypto')
|
||||
|
||||
test('basic examples', function (t) {
|
||||
{
|
||||
const s = z32.encode('Example z-base-32')
|
||||
const b = z32.decode(s)
|
||||
|
||||
t.is(s, 'eihgn5mopt11y6tpcjozg3jpgc3y')
|
||||
t.is(b.toString(), 'Example z-base-32')
|
||||
}
|
||||
|
||||
{
|
||||
const s = z32.encode('The quick brown fox jumps over the lazy dog. 👀')
|
||||
const b = z32.decode(s)
|
||||
|
||||
t.is(s, 'ktwgkedtqiwsg43ycj3g675qrbug66bypj4s4hdurbzzc3m1rb4go3jyptozw6jyctzsqmty6nx3dyy')
|
||||
t.is(b.toString(), 'The quick brown fox jumps over the lazy dog. 👀')
|
||||
}
|
||||
})
|
||||
|
||||
test('random buffers', function (t) {
|
||||
for (let i = 0; i < 1e5; i++) {
|
||||
const b = crypto.randomBytes(Math.round(Math.random() * 100))
|
||||
const s = z32.encode(b)
|
||||
const o = z32.decode(s)
|
||||
|
||||
if (!b4a.equals(o, b)) {
|
||||
t.alike(o, b)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
t.pass('all random buffers passed')
|
||||
})
|
||||
|
||||
test('bad inputs', function (t) {
|
||||
t.exception(function () {
|
||||
z32.decode('!!!')
|
||||
})
|
||||
t.exception(function () {
|
||||
z32.decode('~~~')
|
||||
})
|
||||
t.exception(function () {
|
||||
z32.decode('I1I1I1')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user