@multiformats/multiaddr-matcher
Version:
Match different multiaddr formats
168 lines • 4.39 kB
JavaScript
import { base58btc } from 'multiformats/bases/base58';
import { base64url } from 'multiformats/bases/base64';
/**
* Split a multiaddr into path components
*/
const toParts = (ma) => {
return ma.toString().split('/').slice(1);
};
export const func = (fn) => {
return {
match: (vals) => {
if (vals.length < 1) {
return false;
}
if (fn(vals[0])) {
return vals.slice(1);
}
return false;
},
pattern: 'fn'
};
};
export const literal = (str) => {
return {
match: (vals) => func((val) => val === str).match(vals),
pattern: str
};
};
export const string = () => {
return {
match: (vals) => func((val) => typeof val === 'string').match(vals),
pattern: '{string}'
};
};
export const number = () => {
return {
match: (vals) => func((val) => !isNaN(parseInt(val))).match(vals),
pattern: '{number}'
};
};
export const peerId = () => {
return {
match: (vals) => {
if (vals.length < 2) {
return false;
}
if (vals[0] !== 'p2p' && vals[0] !== 'ipfs') {
return false;
}
// Q is RSA, 1 is Ed25519 or Secp256k1
if (vals[1].startsWith('Q') || vals[1].startsWith('1')) {
try {
base58btc.decode(`z${vals[1]}`);
}
catch (err) {
return false;
}
}
else {
return false;
}
return vals.slice(2);
},
pattern: '/p2p/{peerid}'
};
};
export const certhash = () => {
return {
match: (vals) => {
if (vals.length < 2) {
return false;
}
if (vals[0] !== 'certhash') {
return false;
}
try {
base64url.decode(vals[1]);
}
catch {
return false;
}
return vals.slice(2);
},
pattern: '/certhash/{certhash}'
};
};
export const optional = (matcher) => {
return {
match: (vals) => {
const result = matcher.match(vals);
if (result === false) {
return vals;
}
return result;
},
pattern: `optional(${matcher.pattern})`
};
};
export const or = (...matchers) => {
return {
match: (vals) => {
let matches;
for (const matcher of matchers) {
const result = matcher.match(vals);
// no match
if (result === false) {
continue;
}
// choose greediest matcher
if (matches == null || result.length < matches.length) {
matches = result;
}
}
if (matches == null) {
return false;
}
return matches;
},
pattern: `or(${matchers.map(m => m.pattern).join(', ')})`
};
};
export const and = (...matchers) => {
return {
match: (vals) => {
for (const matcher of matchers) {
// pass what's left of the array
const result = matcher.match(vals);
// no match
if (result === false) {
return false;
}
vals = result;
}
return vals;
},
pattern: `and(${matchers.map(m => m.pattern).join(', ')})`
};
};
export function fmt(...matchers) {
function match(ma) {
let parts = toParts(ma);
for (const matcher of matchers) {
const result = matcher.match(parts);
if (result === false) {
return false;
}
parts = result;
}
return parts;
}
function matches(ma) {
const result = match(ma);
return result !== false;
}
function exactMatch(ma) {
const result = match(ma);
if (result === false) {
return false;
}
return result.length === 0;
}
return {
matchers,
matches,
exactMatch
};
}
//# sourceMappingURL=utils.js.map