commit fcd249d382dc369870bcc89046595983f679edf4
parent a23d08314790f6edbe7f0df9bc64c00a23d4cfd0
Author: Jared Tobin <jared@jtobin.io>
Date: Mon, 8 Oct 2018 10:09:11 +1300
Merge pull request #8 from urbit/jt-add-inv-patq
Add hex2patq and patq2hex functions
Diffstat:
4 files changed, 78 insertions(+), 8 deletions(-)
diff --git a/package.json b/package.json
@@ -4,7 +4,7 @@
"description": "utilities to convert urbit ship names back and forth between @p and @ud",
"main": "dist/index.js",
"scripts": {
- "test": "jest",
+ "test": "jest test/*.test.js && mocha test/property.js",
"build": "gulp"
},
"keywords": [
@@ -15,21 +15,24 @@
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0-beta.34",
- "isomorphic-webcrypto": "^1.6.0",
+ "babel-jest": "^23.4.2",
+ "chai": "^4.2.0",
"gulp": "github:gulpjs/gulp#4.0",
+ "isomorphic-webcrypto": "^1.6.0",
+ "jest": "^23.5.0",
+ "jsverify": "^0.8.3",
+ "mocha": "^5.2.0",
+ "regenerator-runtime": "^0.12.1",
"rollup-plugin-babel": "github:rollup/rollup-plugin-babel",
"rollup-plugin-commonjs": "^8.3.0",
"rollup-plugin-json": "^3.0.0",
"rollup-plugin-node-builtins": "^2.1.2",
+ "rollup-plugin-node-globals": "^1.2.1",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-root-import": "^0.2.3",
"rollup-stream": "^1.24.1",
- "vinyl-source-stream": "^2.0.0",
- "babel-jest": "^23.4.2",
- "jest": "^23.5.0",
- "regenerator-runtime": "^0.12.1",
- "rollup-plugin-node-globals": "^1.2.1"
+ "vinyl-source-stream": "^2.0.0"
},
"dependencies": {
"babel-plugin-lodash": "^3.3.4",
diff --git a/src/index.js b/src/index.js
@@ -4,7 +4,7 @@
const bnjs = require('bn.js')
const { reduce, concat, chunk, isUndefined,
- isString, every, map } = require('lodash')
+ isString, every, map, split } = require('lodash')
const raku = [
3077398253,
@@ -51,6 +51,12 @@ remlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun\
lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes\
`
+// split string at the indicated index
+const splitAt = (index, str) => [str.slice(0, index), str.slice(index)];
+
+// convert a decimal number to a hex string
+const dec2hex = dec => dec.toString(16).padStart(2, '0')
+
// groups suffixes into array of syllables
const suffixes = suf.match(/.{1,3}/g)
@@ -398,6 +404,21 @@ const patq = (n) => {
acc + (acc === '~' ? '' : '-') + name(elem), '~')
}
+hex2patq = hex => patq(new bnjs(hex, 'hex'))
+
+patq2hex = str => {
+ const chunks = split(str.slice(1), '-')
+ const splat = map(chunks, chunk => {
+ let syls = splitAt(3, chunk)
+ let hex =
+ syls[1] === ''
+ ? dec2hex(getSuffixIndex(syls[0]))
+ : dec2hex(getPrefixIndex(syls[0])) +
+ dec2hex(getSuffixIndex(syls[1]))
+ return hex
+ })
+ return splat.join('')
+}
// returns the class of a ship from it's name
const tierOfpatp = name => {
@@ -544,6 +565,8 @@ module.exports = {
patp: patp,
patq: patq,
+ hex2patq: hex2patq,
+ patq2hex: patq2hex,
sein: sein,
_clan: clan,
diff --git a/test/core.test.js b/test/core.test.js
@@ -155,6 +155,12 @@ test('patq correctly encodes 0x1010101010101010102 as @q', () => {
expect(ob.patq(input)).toBe(expected);
});
+test('hex2patq works', () => {
+ let hex = '6d7920617765736f6d65207572626974207469636b65742c206920616d20736f206c75636b79';
+ let expected = '~tastud-holruc-sidwet-salpel-taswet-holdeg-paddec-davdut-holdut-davwex-balwet-divwen-holdet-holruc-taslun-salpel-holtux-dacwex-baltud';
+ expect(ob.hex2patq(hex)).toBe(expected);
+})
+
test('clan works as expected', () => {
expect(ob._clan(new bnjs(0))).toBe('czar');
expect(ob._clan(new bnjs(255))).toBe('czar');
diff --git a/test/property.js b/test/property.js
@@ -0,0 +1,38 @@
+
+const expect = require('chai').expect
+const jsc = require('jsverify')
+const ob = require('../src')
+const bn = require('bn.js')
+
+removeLeadingZeroBytes = str =>
+ str.slice(0, 2) === '00'
+ ? removeLeadingZeroBytes(str.slice(2))
+ : str
+
+eqModLeadingZeroBytes = (s, t) =>
+ removeLeadingZeroBytes(s) === removeLeadingZeroBytes(t)
+
+describe('@q encoding', () => {
+ let hexString = jsc.string.smap(
+ x => Buffer.from(x).toString('hex'),
+ x => Buffer.from(x, 'hex').toString()
+ )
+
+ let patq = hexString.smap(
+ hex => ob.patq(new bn(hex, 'hex')),
+ pq => ob.patq2hex(pq)
+ )
+
+ it('patq2hex and hex2patq are inverses', () => {
+ let iso0 = jsc.forall(hexString, hex =>
+ eqModLeadingZeroBytes(ob.patq2hex(ob.hex2patq(hex)), hex)
+ )
+
+ let iso1 = jsc.forall(patq, str =>
+ ob.hex2patq(ob.patq2hex(str)) === str
+ )
+
+ jsc.assert(iso0)
+ jsc.assert(iso1)
+ })
+})