Compare commits

...

2 Commits

Author SHA1 Message Date
qntm f2f853c0ff NPM IGNORE MEgit add .! 2020-01-29 23:33:18 +00:00
qntm 2bddc5473e Omegaupdate 2020-01-29 23:32:06 +00:00
10 changed files with 8171 additions and 185 deletions

7
.editorconfig Normal file
View File

@ -0,0 +1,7 @@
[*]
insert_final_newline = true
[{*.js,*.json}]
charset = utf-8
indent_style = space
indent_size = 2

2
.gitignore vendored
View File

@ -46,3 +46,5 @@ Network Trash Folder
Temporary Items
.apdisk
node_modules
coverage
dist

2
.npmignore Normal file
View File

@ -0,0 +1,2 @@
*
!dist/**/*

View File

@ -37,39 +37,53 @@ npm install base1
## Usage
```js
var base1 = require("base1");
import { encodeL, encode, decodeL, decode } from 'base1'
var buf = new Buffer([0x03, 0xC0]);
const uint8Array = Uint8Array.from([0x03, 0xC0])
var l = base1.encodeL(buf); // 1217
var str = base1.encode(buf); // "AAAAAAAAAAAA...AA", string is 1,217 characters long
const l = encodeL(uint8Array) // 1217n
const str = encode(uint8Array) // "AAAAAAAAAAAA...AA", string is 1,217 characters long
var buf2 = base1.decode(str); // <Buffer 03 c0>
var buf3 = base1.decodeL(l); // <Buffer 03 c0>
const uint8Array2 = decode(str) // Uint8Array [ 3, 192 ]
const uint8Array3 = decodeL(l) // Uint8Array [ 3, 192 ]
```
### In the browser
Load this file in the browser to gain access to a `base1` global.
```html
<script src="https://unpkg.com/base1" crossorigin></script>
<script>
console.log(base1.decode('AAAAAAAAAAAAAAAAAAAAAAAAAA'))
</script>
```
## API
### base1.encodeL(buf)
`base1` accepts and returns `Uint8Array`s. Note that every Node.js `Buffer` is a `Uint8Array`. A `Uint8Array` can be converted to a Node.js `Buffer` like so:
Input a `Buffer`. Returns a Base1 string length (i.e. a non-negative integer). If this number cannot be represented as a JavaScript number, which is increasingly likely as buffer length increases, returns a string containing its decimal digits.
```js
const buffer = Buffer.from(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength)
```
* The first buffer for which a string is returned is the 7-byte sequence 0x1E 0xFE 0xFE 0xFE 0xFE 0xFF 0x00, which returns the string `"9007199254740993"`.
* The last buffer for which a number is returned is the 128-byte sequence 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xF6 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFF 0x00, which returns `Number.MAX_VALUE` = 2<sup>1024</sup> - 2<sup>971</sup> = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369.
### encodeL(uint8Array)
### base1.encode(buf)
Input a `Uint8Array`. Returns a Base1 string length, in the form of a BigInt.
Encodes a `Buffer` as a Base1 string. This method calls `base1.encodeL` to get a length `l` and then returns a string which is `l` repetitions of "A" in a row.
### encode(uint8Array)
JavaScript specifies no maximum length for a string, although MDN's polyfill for [`String.prototype.repeat`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/repeat) gives an upper limit of 2<sup>28</sup> - 1 = 268,435,455 characters. This is equivalent to the 4-byte sequence 0x0E 0xFE 0xFE 0xFE. Buffers which are longer or lexicographically greater than this may cause errors in your JavaScript engine.
Encodes a `Uint8Array` as a Base1 string. This method calls `base1.encodeL` to get a length `l` and then returns a string which is `l` repetitions of "A" in a row.
### base1.decodeL(l)
JavaScript does not specify, nor does `base1` enforce, a maximum length for a string. However, MDN's polyfill for [`String.prototype.repeat`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/repeat) gives an upper limit of 2<sup>28</sup> - 1 = 268,435,455 characters. This is equivalent to the 4-byte sequence 0x0E 0xFE 0xFE 0xFE. Buffers which are longer or lexicographically greater than this may cause errors in your JavaScript engine.
Take a Base1 string length in the form of a non-negative integer, a non-negative integer expressed as a decimal string or a `big-integer` object and return the `Buffer` it represents.
### decodeL(l)
### base1.decode(str)
Take a Base1 string length in the form of a BigInt and return a `Uint8Array` containing the data which it represents.
Decode a Base1 string and return the `Buffer` it represents.
### decode(str)
Decode a Base1 string and return a `Uint8Array` containing the data which it represents.
## Ports

View File

@ -1,90 +0,0 @@
/**
Converts binary data to and from Base1, whereby the original binary is
converted to an integer `n` and then a string of `n` repetitions of "A".
E.g. base1.encode(new Buffer([17])) = "AAAAAAAAAAAAAAAAAA".
*/
var bigInteger = require("big-integer");
var base = bigInteger(1 << 8);
module.exports = {
/** Encode a buffer as a length `l` */
encodeL: function(buf) {
// First turn binary data into an integer
var l = bigInteger(0);
for(var i = 0; i < buf.length; i++) {
var b = buf[i];
l = l.times(base).plus(b);
}
// Next we need to determine the block.
// Binary of length 0 bytes gives Base1 of length 0 ("")
// Binary of length 1 byte gives Base1 of length 1 ("A") to 256 inclusive
// Binary of length 2 bytes gives Base1 of length 257 to 65792 inclusive
// etc.
var binaryLength = 0, blockSize = base.pow(binaryLength);
while(binaryLength < buf.length) {
l = l.plus(blockSize);
binaryLength++;
blockSize = blockSize.times(base);
}
var number = l.toJSNumber(); // This may lose information.
if (bigInteger(number.toString(2), 2).equals(l)) {
return number;
}
return l.toString(10);
},
encode: function(buf) {
return "A".repeat(this.encodeL(buf));
},
/** Operates on a length `l` */
decodeL: function(l) {
if(typeof l === 'number' && l > Number.MAX_SAFE_INTEGER) {
// Apparently `bigInteger` does not preserve all the decimal digits! So
// use this hack at construction time
l = bigInteger(l.toString(2), 2);
} else {
l = bigInteger(l);
}
// First we need to work out the length in bytes of the original binary.
// Base1 of length 0 ("") means binary is 0 bytes long.
// Base1 of length 1 ("A") to 256 inclusive means binary is 1 byte long.
// Base1 of length 257 to 65792 inclusive means binary is 2 bytes long.
// Base1 of length 65793 to 16843008 inclusive means binary is 3 bytes long.
// etc.
var binaryLength = 0, blockSize = base.pow(binaryLength);
while(l.greaterOrEquals(blockSize)) {
l = l.minus(blockSize);
binaryLength++;
blockSize = blockSize.times(base);
}
// `l` is now the offset into the block, a number from 0 to
// 256 ** `binaryLength` - 1 inclusive. We can populate the buffer from the
// number now.
var buf = new Buffer(binaryLength);
for(var byteNum = binaryLength - 1; byteNum >= 0; byteNum--) {
var b = l.mod(base);
buf[byteNum] = b.toJSNumber();
l = l.minus(b).divide(base);
}
return buf;
},
decode: function(base1) {
// Got to make sure every character is "A". TODO: PERFORMANCE???
var l = base1.length;
for(var i = 0; i < l; i++) {
if(base1.charAt(i) !== "A") {
throw new Error("This is not a valid Base1 string");
}
}
return this.decodeL(l);
}
};

7940
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,15 @@
{
"name": "base1",
"version": "0.1.0",
"version": "1.0.1",
"description": "Convert binary data to Base1",
"homepage": "https://github.com/qntm/base1",
"repository": {
"type": "git",
"url": "git://github.com/qntm/base1.git"
},
"main": "index.js",
"module": "dist/es6/base1.js",
"main": "dist/cjs/base1.js",
"browser": "dist/iife/base1.js",
"keywords": [
"base64",
"base1",
@ -18,11 +20,28 @@
"silly"
],
"scripts": {
"test": "node test/test.js"
"build": "rollup -c rollup.config.js",
"jest": "jest",
"rollup": "rollup",
"standard": "standard",
"test": "standard && jest --coverage"
},
"author": "qntm",
"license": "MIT",
"dependencies": {
"big-integer": "^1.6.23"
"dependencies": {},
"devDependencies": {
"@babel/preset-env": "^7.7.7",
"glob": "^7.1.6",
"jest": "^25.1.0",
"rollup": "^1.29.0",
"standard": "^14.3.1"
},
"babel": {
"presets": [
"@babel/preset-env"
]
},
"standard": {
"ignore": "dist"
}
}

23
rollup.config.js Normal file
View File

@ -0,0 +1,23 @@
module.exports = [{
// nearly indistinguishable from a copy and paste of the source
input: 'src/index.js',
output: {
file: 'dist/es6/base1.js',
format: 'esm'
}
}, {
// same as above but Node.js-friendly
input: 'src/index.js',
output: {
file: 'dist/cjs/base1.js',
format: 'cjs'
}
}, {
// this can be imported into the browser as a script
input: 'src/index.js',
output: {
file: 'dist/iife/base1.js',
format: 'iife',
name: 'base1'
}
}]

44
src/index.js Normal file
View File

@ -0,0 +1,44 @@
/**
Converts binary data to and from Base1, whereby the original binary is
converted to a BigInt `l` and then a string of `l` repetitions of "A".
E.g. base1.encode(new Buffer([17])) = "AAAAAAAAAAAAAAAAAA".
*/
/* global BigInt */
export const encodeL = uint8Array =>
uint8Array.reduce((l, b) => l * 256n + BigInt(b) + 1n, 0n)
export const encode = uint8Array => {
const l = encodeL(uint8Array)
// String.prototype.repeat demands a number, not a BigInt
const number = Number(l) // This can lose information
if (BigInt(number) !== l) {
throw Error('Could not compute the Base1 output length as a number')
}
// This could still throw, JS specifies no string length limit
return 'A'.repeat(number)
}
export const decodeL = l => {
const bytes = []
while (l > 0n) {
l -= 1n
bytes.push(Number(l % 256n))
l /= 256n
}
bytes.reverse()
return Uint8Array.from(bytes)
}
export const decode = base1 => {
// TODO: performance?
if (!/^A*$/.test(base1)) {
throw Error('This is not a valid Base1 string')
}
return decodeL(BigInt(base1.length))
}

View File

@ -1,88 +1,113 @@
/** Tests for base65536, ensure strings survive round trips, etc. */
var base1 = require("../index.js");
var fs = require("fs");
/* eslint-env jest */
/* global BigInt */
console.log(base1.encodeL(new Buffer([ ])) === 0);
console.log(base1.encodeL(new Buffer([ 0])) === 1);
console.log(base1.encodeL(new Buffer([ 17])) === 18);
console.log(base1.encodeL(new Buffer([ 255])) === 256);
console.log(base1.encodeL(new Buffer([ 0, 0])) === 257);
console.log(base1.encodeL(new Buffer([ 255, 255])) === 65792);
console.log(base1.encodeL(new Buffer([ 0, 0, 0])) === 65793);
console.log(base1.encodeL(new Buffer([ 255, 255, 255])) === 16843008);
console.log(base1.encodeL(new Buffer([0, 0, 0, 0])) === 16843009);
import fs from 'fs'
import { encodeL, encode, decodeL, decode } from '../src/index'
console.log(base1.decodeL( 0).equals(new Buffer([ ])));
console.log(base1.decodeL( 1).equals(new Buffer([ 0])));
console.log(base1.decodeL( 18).equals(new Buffer([ 17])));
console.log(base1.decodeL( 256).equals(new Buffer([ 255])));
console.log(base1.decodeL( 257).equals(new Buffer([ 0, 0])));
console.log(base1.decodeL( 65792).equals(new Buffer([ 255, 255])));
console.log(base1.decodeL( 65793).equals(new Buffer([ 0, 0, 0])));
console.log(base1.decodeL(16843008).equals(new Buffer([ 255, 255, 255])));
console.log(base1.decodeL(16843009).equals(new Buffer([0, 0, 0, 0])));
describe('base1', () => {
describe('encodeL and decodeL', () => {
describe('encodeL', () => {
it('works', () => {
expect(encodeL(Uint8Array.from([]))).toBe(0n)
expect(encodeL(Uint8Array.from([0]))).toBe(1n)
expect(encodeL(Uint8Array.from([17]))).toBe(18n)
expect(encodeL(Uint8Array.from([255]))).toBe(256n)
expect(encodeL(Uint8Array.from([0, 0]))).toBe(257n)
expect(encodeL(Uint8Array.from([255, 255]))).toBe(65792n)
expect(encodeL(Uint8Array.from([0, 0, 0]))).toBe(65793n)
expect(encodeL(Uint8Array.from([255, 255, 255]))).toBe(16843008n)
expect(encodeL(Uint8Array.from([0, 0, 0, 0]))).toBe(16843009n)
})
// Edge cases for encodeL and decodeL
console.log(base1.encodeL(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE])) === Number.MAX_SAFE_INTEGER);
console.log(base1.encodeL(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE])) === 9007199254740991);
console.log(base1.encodeL(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF])) === 9007199254740992);
console.log(base1.encodeL(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00])) === "9007199254740993");
it('edge cases', () => {
expect(encodeL(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]))).toBe(BigInt(Number.MAX_SAFE_INTEGER))
expect(encodeL(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]))).toBe(9007199254740991n)
expect(encodeL(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF]))).toBe(9007199254740992n)
expect(encodeL(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00]))).toBe(9007199254740993n)
// One below Number.MAX_VALUE - cannot be represented as a number. Returns a string.
console.log(base1.encodeL(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE])) !== Number.MAX_VALUE);
console.log(base1.encodeL(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE])) === "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858367");
// One below Number.MAX_VALUE
expect(encodeL(Uint8Array.from([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]))).toBe(BigInt(Number.MAX_VALUE) - 1n)
// Exactly Number.MAX_VALUE
console.log(base1.encodeL(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF])) === Number.MAX_VALUE);
console.log(base1.encodeL(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF])) !== "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368");
// Exactly Number.MAX_VALUE
expect(encodeL(Uint8Array.from([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF]))).toBe(BigInt(Number.MAX_VALUE))
// One above Number.MAX_VALUE
console.log(base1.encodeL(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00])) !== Number.MAX_VALUE);
console.log(base1.encodeL(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00])) === "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369");
// One above Number.MAX_VALUE
expect(encodeL(Uint8Array.from([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00]))).toBe(BigInt(Number.MAX_VALUE) + 1n)
})
})
console.log(base1.decodeL(Number.MAX_SAFE_INTEGER).equals(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE])));
console.log(base1.decodeL(9007199254740991).equals(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE])));
console.log(base1.decodeL(9007199254740992).equals(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF])));
console.log(base1.decodeL("9007199254740992").equals(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF])));
console.log(base1.decodeL("9007199254740993").equals(new Buffer([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00])));
describe('decodeL', () => {
it('works', () => {
expect(decodeL(0n)).toEqual(Uint8Array.from([]))
expect(decodeL(1n)).toEqual(Uint8Array.from([0]))
expect(decodeL(18n)).toEqual(Uint8Array.from([17]))
expect(decodeL(256n)).toEqual(Uint8Array.from([255]))
expect(decodeL(257n)).toEqual(Uint8Array.from([0, 0]))
expect(decodeL(65792n)).toEqual(Uint8Array.from([255, 255]))
expect(decodeL(65793n)).toEqual(Uint8Array.from([0, 0, 0]))
expect(decodeL(16843008n)).toEqual(Uint8Array.from([255, 255, 255]))
expect(decodeL(16843009n)).toEqual(Uint8Array.from([0, 0, 0, 0]))
})
console.log(base1.decodeL(Number.MAX_VALUE).equals(new Buffer([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF])));
it('edge cases', () => {
expect(decodeL(BigInt(Number.MAX_SAFE_INTEGER))).toEqual(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]))
expect(decodeL(9007199254740991n)).toEqual(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]))
expect(decodeL(9007199254740992n)).toEqual(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF]))
expect(decodeL(9007199254740993n)).toEqual(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00]))
console.log(base1.decodeL("0").equals(new Buffer([])));
console.log(base1.decodeL(base1.encodeL(Buffer.alloc(10, 1))).equals(Buffer.alloc(10, 1)));
console.log(base1.decodeL(base1.encodeL(Buffer.alloc(100, 1))).equals(Buffer.alloc(100, 1)));
console.log(base1.decodeL(base1.encodeL(Buffer.alloc(1000, 1))).equals(Buffer.alloc(1000, 1)));
console.log(base1.decodeL(base1.encodeL(Buffer.alloc(10000, 1))).equals(Buffer.alloc(10000, 1)));
console.log();
expect(decodeL(BigInt(Number.MAX_VALUE))).toEqual(Uint8Array.from([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF]))
})
})
// encode, decode
describe('round trips', () => {
it('work', () => {
expect(decodeL(encodeL(new Uint8Array(10).fill(1)))).toEqual(new Uint8Array(10).fill(1))
expect(decodeL(encodeL(new Uint8Array(100).fill(1)))).toEqual(new Uint8Array(100).fill(1))
expect(decodeL(encodeL(new Uint8Array(1000).fill(1)))).toEqual(new Uint8Array(1000).fill(1))
expect(decodeL(encodeL(new Uint8Array(10000).fill(1)))).toEqual(new Uint8Array(10000).fill(1))
})
})
})
var pairsDir = "./test/pairs";
fs.readdirSync(pairsDir).forEach(function(fileName) {
if(!fileName.endsWith(".base1")) {
return;
}
var caseName = fileName.substring(0, fileName.length - ".base1".length);
var base1Text = fs.readFileSync(pairsDir + "/" + caseName + ".base1", "utf8");
var binary = fs.readFileSync(pairsDir + "/" + caseName + ".bin");
console.log(base1.decode(base1Text).equals(binary));
console.log(base1.encode(binary) === base1Text);
});
describe('encode and decode', () => {
describe('encode', () => {
it('throws on a bad BigInt length', () => {
expect(() => encode(Uint8Array.from([0x1E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0x00]))).toThrowError('Could not compute the Base1 output length as a number')
})
var badDir = "./test/bad";
fs.readdirSync(badDir).forEach(function(fileName) {
if(!fileName.endsWith(".base1")) {
return;
}
var caseName = fileName.substring(0, fileName.length - ".base1".length);
var base1Text = fs.readFileSync(badDir + "/" + caseName + ".base1", "utf8");
try {
base1.decode(base1Text);
console.log(false);
} catch(e) {
console.log(true);
}
});
it('throws on too large an input', () => {
expect(() => encode(Uint8Array.from([0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF6, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF]))).toThrowError('Invalid string length')
})
})
console.log("OK");
describe('round trips', () => {
const pairsDir = './test/pairs'
fs.readdirSync(pairsDir)
.filter(fileName => fileName.endsWith('.base1'))
.forEach(fileName => {
const caseName = fileName.substring(0, fileName.length - '.base1'.length)
it(caseName, () => {
const base1 = fs.readFileSync(pairsDir + '/' + caseName + '.base1', 'utf8')
const binary = Uint8Array.from(fs.readFileSync(pairsDir + '/' + caseName + '.bin'))
expect(decode(base1)).toEqual(binary)
expect(encode(binary)).toBe(base1)
})
})
})
describe('invalid Base1', () => {
const badDir = './test/bad'
fs.readdirSync(badDir)
.filter(fileName => fileName.endsWith('.base1'))
.forEach(fileName => {
const caseName = fileName.substring(0, fileName.length - '.base1'.length)
it(caseName, () => {
const base1 = fs.readFileSync(badDir + '/' + caseName + '.base1', 'utf8')
expect(() => decode(base1)).toThrowError('This is not a valid Base1 string')
})
})
})
})
})