@multiformats/multiaddr-matcher
Version:
Match different multiaddr formats
172 lines (136 loc) • 3.16 kB
text/typescript
import type { Matcher, MultiaddrMatcher } from './index.js'
import type { Multiaddr, Component } from '@multiformats/multiaddr'
/**
* Matches a multiaddr component with the specified code but no value
*/
export const code = (code: number): Matcher => {
return {
match: (vals) => {
const component = vals[0]
if (component == null) {
return false
}
if (component.code !== code) {
return false
}
if (component.value != null) {
return false
}
return vals.slice(1)
}
}
}
/**
* Matches a multiaddr component with the specified code and value. If the value
* is omitted any non-undefined value is matched.
*/
export const value = (code: number, value?: string): Matcher => {
return {
match: (vals) => {
const component = vals[0]
if (component?.code !== code) {
return false
}
if (component.value == null) {
return false
}
if (value != null && component.value !== value) {
return false
}
return vals.slice(1)
}
}
}
/**
* An optional matcher
*/
export const optional = (matcher: Matcher): Matcher => {
return {
match: (vals) => {
const result = matcher.match(vals)
if (result === false) {
return vals
}
return result
}
}
}
/**
* Matches any one of the passed matches
*/
export const or = (...matchers: Matcher[]): Matcher => {
return {
match: (vals) => {
let matches: Component[] | undefined
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
}
}
}
/**
* Matches all of the passed matchers
*/
export const and = (...matchers: Matcher[]): Matcher => {
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
}
}
}
/**
* Create a multiaddr matcher from the passed component matchers
*/
export function fmt (...matchers: Matcher[]): MultiaddrMatcher {
function match (ma?: Multiaddr): Component[] | false {
if (ma == null) {
return false
}
let parts = ma.getComponents()
for (const matcher of matchers) {
const result = matcher.match(parts)
if (result === false) {
return false
}
parts = result
}
return parts
}
function matches (ma?: Multiaddr): boolean {
const result = match(ma)
return result !== false
}
function exactMatch (ma?: Multiaddr): boolean {
const result = match(ma)
if (result === false) {
return false
}
return result.length === 0
}
return {
matchers,
matches,
exactMatch
}
}