Skip to content
This repository was archived by the owner on Aug 24, 2021. It is now read-only.

Commit 613363b

Browse files
authored
feat: more encoding, errors, spec tests (#55)
- adds support for all the encodings in https://github.com/multiformats/multibase/blob/master/multibase.csv - better errors showing the invalid chars and inputs - `names` and `codes` exports the full object that maps names/codes to base instances - you can use these to get the unprefixed base encoder/decoder - two new methods exported, `encoding` and `encodingFromData` - you can use these to get the unprefixed base encoder/decoder - adds all the spec tests https://github.com/multiformats/multibase/tree/master/tests - its also faster check benchmarks below This module now only uses 2 base encoding implementations, 1 generalised rfc4648 and 1 generalised btc like. closes #49 closes #38 closes #46 closes #53 closes #26 BREAKING CHANGE: `names` and `codes` export the full object that maps names/codes to base instances instead of just the keys
1 parent 5ea2ce7 commit 613363b

19 files changed

+572
-328
lines changed

.travis.yml

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ jobs:
2121
include:
2222
- stage: check
2323
script:
24-
- npx aegir commitlint --travis
2524
- npx aegir dep-check
2625
- npm run lint
2726

README.md

+22-92
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ js-multibase
1717
## Table of Contents
1818

1919
- [Install](#install)
20-
- [In Node.js through npm](#in-nodejs-through-npm)
21-
- [Browser: Browserify, Webpack, other bundlers](#browser-browserify-webpack-other-bundlers)
20+
- [NPM](#npm)
2221
- [In the Browser through `<script>` tag](#in-the-browser-through-script-tag)
23-
- [Gotchas](#gotchas)
2422
- [Usage](#usage)
2523
- [Example](#example)
2624
- [API](#api)
@@ -37,10 +35,10 @@ js-multibase
3735

3836
## Install
3937

40-
### In Node.js through npm
38+
### NPM
4139

42-
```bash
43-
> npm install --save multibase
40+
```sh
41+
$ npm install --save multibase
4442
```
4543

4644
The type definitions for this package are available on http://definitelytyped.org/. To install just use:
@@ -49,23 +47,12 @@ The type definitions for this package are available on http://definitelytyped.or
4947
$ npm install -D @types/multibase
5048
```
5149

52-
### Browser: Browserify, Webpack, other bundlers
53-
54-
The code published to npm that gets loaded on require is in fact an ES5 transpiled version with the right shims added. This means that you can require it and use with your favourite bundler without having to adjust asset management process.
55-
56-
```js
57-
const multibase = require('multibase')
58-
```
59-
60-
6150
### In the Browser through `<script>` tag
6251

6352
Loading this module through a script tag will make the ```Multibase``` obj available in the global namespace.
6453

6554
```html
6655
<script src="https://unpkg.com/multibase/dist/index.min.js"></script>
67-
<!-- OR -->
68-
<script src="https://unpkg.com/multibase/dist/index.js"></script>
6956
```
7057

7158
## Usage
@@ -86,111 +73,54 @@ console.log(decodedBuf.toString())
8673
## API
8774
https://multiformats.github.io/js-multibase/
8875

89-
### `multibase` - Prefixes an encoded buffer with its multibase code
76+
#### `multibase` - Prefixes an encoded buffer with its multibase code
9077

9178
```
9279
const multibased = multibase(<nameOrCode>, encodedBuf)
9380
```
9481

95-
### `multibase.encode` - Encodes a buffer into one of the supported encodings, prefixing it with the multibase code
82+
#### `multibase.encode` - Encodes a buffer into one of the supported encodings, prefixing it with the multibase code
9683

9784
```JavaScript
9885
const encodedBuf = multibase.encode(<nameOrCode>, <buf>)
9986
```
10087

101-
### `multibase.decode` - Decodes a buffer or string
88+
#### `multibase.decode` - Decodes a buffer or string
10289

10390
```JavaScript
10491
const decodedBuf = multibase.decode(bufOrString)
10592
```
10693

107-
### `multibase.isEncoded` - Checks if buffer or string is encoded
94+
#### `multibase.isEncoded` - Checks if buffer or string is encoded
10895

10996
```JavaScript
11097
const value = multibase.isEncoded(bufOrString)
11198
// value is the name of the encoding if it is encoded, false otherwise
11299
```
113100

114-
### `multibase.names`
115-
116-
A frozen `Array` of supported base encoding names.
117-
118-
### `multibase.codes`
119-
120-
A frozen `Array` of supported base encoding codes.
101+
#### `multibase.encoding` - Get the encoding by name or code
121102

122-
### Supported Encodings, see [`src/constants.js`](/src/constants.js)
123-
124-
## Architecture and Encoding/Decoding
125-
126-
Multibase package defines all the supported bases and the location of their implementation in the constants.js file. A base is a class with a name, a code, an implementation and an alphabet.
127-
```js
128-
class Base {
129-
constructor (name, code, implementation, alphabet) {
130-
//...
131-
}
132-
// ...
133-
}
103+
```JavaScript
104+
const value = multibase.encoding(nameOrCode)
105+
// value is an instance of the corresponding `Base`
134106
```
135-
The ```implementation``` is an object where the encoding/decoding functions are implemented. It must take one argument, (the alphabet) following the [base-x module](https://github.com/cryptocoinjs/base-x) architecture.
136-
137-
The ```alphabet``` is the **ordered** set of defined symbols for a given base.
138107

139-
The idea behind this is that several bases may have implementations from different locations/modules so it's useful to have an object (and a summary) of all of them in one location (hence the constants.js).
108+
#### `multibase.encodingFromData` - Get the encoding from data either a `string` or `Buffer`
140109

141-
All the supported bases are currently using the npm [base-x](https://github.com/cryptocoinjs/base-x) module as their implementation. It is using bitwise maipulation to go from one base to another, so this module does not support padding at the moment.
110+
```JavaScript
111+
const value = multibase.encodingFromData(data)
112+
// value is an instance of the corresponding `Base`
113+
```
142114

143-
## Adding additional bases
115+
#### `multibase.names`
144116

145-
If the base you are looking for is not supported yet in js-multibase and you know a good encoding/decoding algorithm, you can add support for this base easily by editing the constants.js file
146-
(**you'll need to create an issue about that beforehand since a code and a canonical name have to be defined**):
117+
A frozen `Object` of supported base encoding names mapped to the corresponding `Base` instance.
147118

148-
```js
149-
const baseX = require('base-x')
150-
//const newPackage = require('your-package-name')
119+
#### `multibase.codes`
151120

152-
const constants = [
153-
['base2', '0', baseX, '01'],
154-
['base8', '7', baseX, '01234567'],
155-
// ... [ 'your-base-name', 'code-to-be-defined', newPackage, 'alphabet']
156-
]
157-
```
158-
The required package defines the implementation of the encoding/decoding process. **It must comply by these rules** :
159-
- `encode` and `decode` functions with to-be-encoded buffer as the only expected argument
160-
- the require call use the `alphabet` given as an argument for the encoding/decoding process
161-
162-
*If no package is specified , it means the base is not implemented yet*
163-
164-
Adding a new base requires the tests to be updated. Test files to be updated are :
165-
- constants.spec.js
166-
```js
167-
describe('constants', () => {
168-
it('constants indexed by name', () => {
169-
const names = constants.names
170-
expect(Object.keys(names).length).to.equal(constants-count) // currently 12
171-
})
172-
173-
it('constants indexed by code', () => {
174-
const codes = constants.codes
175-
expect(Object.keys(codes).length).to.equal(constants-count)
176-
})
177-
})
178-
```
121+
A frozen `Object` of supported base encoding codes mapped to the corresponding `Base` instance.
179122

180-
- multibase.spec.js
181-
- if the base is implemented
182-
```js
183-
const supportedBases = [
184-
['base2', 'yes mani !', '01111001011001010111001100100000011011010110000101101110011010010010000000100001'],
185-
['base8', 'yes mani !', '7171312714403326055632220041'],
186-
['base10', 'yes mani !', '9573277761329450583662625'],
187-
// ... ['your-base-name', 'what you want', 'expected output']
188-
```
189-
- if the base is not implemented yet
190-
```js
191-
const supportedBases = [
192-
// ... ['your-base-name']
193-
```
123+
### Supported Encodings, see [`src/constants.js`](/src/constants.js)
194124

195125
## Contribute
196126

benchmark.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* eslint-disable no-console */
2+
'use strict'
3+
const Benchmark = require('benchmark')
4+
const multibase = require('./src')
5+
6+
const names = Object.keys(multibase.names)
7+
const suite = new Benchmark.Suite()
8+
const input = 'Decentralize everything!!'
9+
10+
for (const enc of names) {
11+
suite.add(enc, () => {
12+
multibase.encode(enc, Buffer.from(input))
13+
})
14+
}
15+
16+
suite
17+
.on('cycle', function (event) {
18+
console.log(String(event.target))
19+
})
20+
.on('complete', function () {
21+
console.log('Fastest is ' + this.filter('fastest').map('name'))
22+
})
23+
.run({ async: true })

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
},
4040
"devDependencies": {
4141
"aegir": "^22.0.0",
42+
"benchmark": "^2.1.4",
4243
"chai": "^4.1.2",
4344
"dirty-chai": "^2.0.1",
4445
"pre-commit": "^1.2.2"

src/base.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ class Base {
44
constructor (name, code, implementation, alphabet) {
55
this.name = name
66
this.code = code
7+
this.codeBuf = Buffer.from(this.code)
78
this.alphabet = alphabet
8-
if (implementation && alphabet) {
9-
this.engine = implementation(alphabet)
10-
}
11-
}
12-
13-
encode (stringOrBuffer) {
14-
return this.engine.encode(stringOrBuffer)
9+
this.engine = implementation(alphabet)
1510
}
1611

17-
decode (stringOrBuffer) {
18-
return this.engine.decode(stringOrBuffer)
12+
encode (buf) {
13+
return this.engine.encode(buf)
1914
}
2015

21-
isImplemented () {
22-
return this.engine
16+
decode (string) {
17+
for (const char of string) {
18+
if (this.alphabet && this.alphabet.indexOf(char) < 0) {
19+
throw new Error(`invalid character '${char}' in '${string}'`)
20+
}
21+
}
22+
return this.engine.decode(string)
2323
}
2424
}
2525

src/base16.js

-21
This file was deleted.

src/base32.js

-81
This file was deleted.

0 commit comments

Comments
 (0)