multiformats
Version:
Interface for multihash, multicodec, multibase and CID
109 lines (105 loc) • 2.93 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
class Encoder {
constructor(name, prefix, baseEncode) {
this.name = name;
this.prefix = prefix;
this.baseEncode = baseEncode;
}
encode(bytes) {
if (bytes instanceof Uint8Array) {
return `${ this.prefix }${ this.baseEncode(bytes) }`;
} else {
throw Error('Unknown type, must be binary type');
}
}
}
class Decoder {
constructor(name, prefix, baseDecode) {
this.name = name;
this.prefix = prefix;
this.baseDecode = baseDecode;
}
decode(text) {
if (typeof text === 'string') {
switch (text[0]) {
case this.prefix: {
return this.baseDecode(text.slice(1));
}
default: {
throw Error(`Unable to decode multibase string ${ JSON.stringify(text) }, ${ this.name } decoder only supports inputs prefixed with ${ this.prefix }`);
}
}
} else {
throw Error('Can only multibase decode strings');
}
}
or(decoder) {
const decoders = {
[this.prefix]: this,
...decoder.decoders || { [decoder.prefix]: decoder }
};
return new ComposedDecoder(decoders);
}
}
class ComposedDecoder {
constructor(decoders) {
this.decoders = decoders;
}
or(decoder) {
const other = decoder.decoders || { [decoder.prefix]: decoder };
return new ComposedDecoder({
...this.decoders,
...other
});
}
decode(input) {
const prefix = input[0];
const decoder = this.decoders[prefix];
if (decoder) {
return decoder.decode(input);
} else {
throw RangeError(`Unable to decode multibase string ${ JSON.stringify(input) }, only inputs prefixed with ${ Object.keys(this.decoders) } are supported`);
}
}
}
class Codec {
constructor(name, prefix, baseEncode, baseDecode) {
this.name = name;
this.prefix = prefix;
this.baseEncode = baseEncode;
this.baseDecode = baseDecode;
this.encoder = new Encoder(name, prefix, baseEncode);
this.decoder = new Decoder(name, prefix, baseDecode);
}
encode(input) {
return this.encoder.encode(input);
}
decode(input) {
return this.decoder.decode(input);
}
}
const withAlphabet = ({name, prefix, encode, decode, alphabet}) => from({
name,
prefix,
encode: input => encode(input, alphabet),
decode: input => {
for (const char of input) {
if (alphabet.indexOf(char) < 0) {
throw new Error(`invalid ${ name } character`);
}
}
return decode(input, alphabet);
}
});
const withSettings = ({name, prefix, settings, encode, decode}) => from({
name,
prefix,
encode: input => encode(input, settings),
decode: input => decode(input, settings)
});
const from = ({name, prefix, encode, decode}) => new Codec(name, prefix, encode, decode);
exports.Codec = Codec;
exports.from = from;
exports.withAlphabet = withAlphabet;
exports.withSettings = withSettings;
;