From 50ff583b4ca89fa2e4935390ca9817926f3d76fe Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Tue, 11 Jul 2023 12:31:58 +0700 Subject: [PATCH 1/4] feat: get path and tuples on constructor --- src/codec.ts | 28 ++++++++++++++++++---------- src/index.ts | 5 ++++- test/codec.spec.ts | 22 +++++++++++++++------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/codec.ts b/src/codec.ts index 0c870401..0d5ebd97 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -68,17 +68,25 @@ export function stringTuplesToString (tuples: StringTuple[]): string { /** * [[str name, str addr]... ] -> [[int code, Uint8Array]... ] */ -export function stringTuplesToTuples (tuples: Array): Tuple[] { - return tuples.map((tup) => { +export function stringTuplesToTuples (stringTuples: Array): { tuples: Tuple[], path: string | null } { + let path: string | null | undefined + const tuples = stringTuples.map((tup) => { if (!Array.isArray(tup)) { tup = [tup] } const proto = protoFromTuple(tup) - if (tup.length > 1) { - return [proto.code, convertToBytes(proto.code, tup[1])] + const tuple: Tuple = (tup.length > 1) ? [proto.code, convertToBytes(proto.code, tup[1])] : [proto.code] + if (path === undefined && proto.path === true) { + path = tuple[1] != null ? convertToString(proto.code, tuple[1]) : null } - return [proto.code] + return tuple }) + + if (path == null) { + path = null + } + + return { tuples, path } } /** @@ -171,18 +179,18 @@ export function bytesToString (buf: Uint8Array): string { /** * String -> Uint8Array */ -export function stringToBytes (str: string): Uint8Array { +export function stringToBytes (str: string): { bytes: Uint8Array, tuples: Tuple[], path: string | null } { str = cleanPath(str) - const a = stringToStringTuples(str) - const b = stringTuplesToTuples(a) + const stringTuples = stringToStringTuples(str) + const { tuples, path } = stringTuplesToTuples(stringTuples) - return tuplesToBytes(b) + return { bytes: tuplesToBytes(tuples), tuples, path } } /** * String -> Uint8Array */ -export function fromString (str: string): Uint8Array { +export function fromString (str: string): { bytes: Uint8Array, tuples: Tuple[], path: string | null } { return stringToBytes(str) } diff --git a/src/index.ts b/src/index.ts index e65323b9..920a5bab 100644 --- a/src/index.ts +++ b/src/index.ts @@ -513,7 +513,10 @@ class DefaultMultiaddr implements Multiaddr { if (addr.length > 0 && addr.charAt(0) !== '/') { throw new Error(`multiaddr "${addr}" must start with a "/"`) } - this.bytes = codec.fromString(addr) + const { bytes, tuples, path } = codec.fromString(addr) + this.bytes = bytes + this.#tuples = tuples + this.#path = path } else if (isMultiaddr(addr)) { // Multiaddr this.bytes = codec.fromBytes(addr.bytes) // validate + copy buffer } else { diff --git a/test/codec.spec.ts b/test/codec.spec.ts index b5413012..2d5efad6 100644 --- a/test/codec.spec.ts +++ b/test/codec.spec.ts @@ -3,6 +3,7 @@ import { expect } from 'aegir/chai' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import varint from 'varint' import * as codec from '../src/codec.js' +import { convertToBytes } from '../src/convert.js' describe('codec', () => { describe('.stringToStringTuples', () => { @@ -16,13 +17,20 @@ describe('codec', () => { }) describe('.stringTuplesToTuples', () => { - it('handles non array tuples', () => { - expect( - codec.stringTuplesToTuples([['ip4', '0.0.0.0'], 'utp']) - ).to.eql( - [[4, Uint8Array.from([0, 0, 0, 0])], [302]] - ) - }) + const testCases: Array<{ name: string, stringTuples: Array, tuples: Array<[number, Uint8Array?]>, path: string | null }> = [ + { name: 'handles non array tuples', stringTuples: [['ip4', '0.0.0.0'], 'utp'], tuples: [[4, Uint8Array.from([0, 0, 0, 0])], [302]], path: null }, + { name: 'handle not null path', stringTuples: [['unix', '/tmp/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')]], path: '/tmp/p2p.sock' } + ] + + for (const { name, stringTuples, tuples, path } of testCases) { + it(name, () => { + expect( + codec.stringTuplesToTuples(stringTuples) + ).to.eql( + { tuples, path } + ) + }) + } }) describe('.tuplesToStringTuples', () => { From d925f3b21b88b30c833d2a19f28878c76480d72b Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Wed, 12 Jul 2023 14:41:59 +0700 Subject: [PATCH 2/4] chore: add more types and fix function's comments --- src/codec.ts | 17 +++++++++-------- src/index.ts | 16 ++++++++++++++-- test/codec.spec.ts | 3 ++- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/codec.ts b/src/codec.ts index 0d5ebd97..a0bb55a0 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -3,7 +3,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import varint from 'varint' import { convertToBytes, convertToString } from './convert.js' import { getProtocol } from './protocols-table.js' -import type { StringTuple, Tuple, Protocol } from './index.js' +import type { StringTuple, Tuple, Protocol, MultiaddrInputString, MultiaddrInputStringResult } from './index.js' /** * string -> [[str name, str addr]... ] @@ -66,9 +66,10 @@ export function stringTuplesToString (tuples: StringTuple[]): string { } /** - * [[str name, str addr]... ] -> [[int code, Uint8Array]... ] + * [[str name, str addr]... ] -> {tuples: [[int code, Uint8Array]... ], path: str} + * The logic to get path is the same to DefaultMultiaddr.getPath() */ -export function stringTuplesToTuples (stringTuples: Array): { tuples: Tuple[], path: string | null } { +export function stringTuplesToTuples (stringTuples: Array): Omit { let path: string | null | undefined const tuples = stringTuples.map((tup) => { if (!Array.isArray(tup)) { @@ -177,9 +178,9 @@ export function bytesToString (buf: Uint8Array): string { } /** - * String -> Uint8Array + * MultiaddrInputString -> MultiaddrInputStringResult */ -export function stringToBytes (str: string): { bytes: Uint8Array, tuples: Tuple[], path: string | null } { +export function parseMultiaddrInputString (str: MultiaddrInputString): MultiaddrInputStringResult { str = cleanPath(str) const stringTuples = stringToStringTuples(str) const { tuples, path } = stringTuplesToTuples(stringTuples) @@ -188,10 +189,10 @@ export function stringToBytes (str: string): { bytes: Uint8Array, tuples: Tuple[ } /** - * String -> Uint8Array + * MultiaddrInputString -> MultiaddrInputStringResult */ -export function fromString (str: string): { bytes: Uint8Array, tuples: Tuple[], path: string | null } { - return stringToBytes(str) +export function fromMultiaddrInputString (str: MultiaddrInputString): MultiaddrInputStringResult { + return parseMultiaddrInputString(str) } /** diff --git a/src/index.ts b/src/index.ts index 920a5bab..f1ec0bd0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,10 +60,15 @@ export interface NodeAddress { port: number } +/** + * Represent a multiaaddr input string + */ +export type MultiaddrInputString = string + /** * These types can be parsed into a {@link Multiaddr} object */ -export type MultiaddrInput = string | Multiaddr | Uint8Array | null +export type MultiaddrInput = MultiaddrInputString | Multiaddr | Uint8Array | null /** * A Resolver is a function that takes a {@link Multiaddr} and resolves it into one @@ -81,6 +86,13 @@ export type Tuple = [number, Uint8Array?] */ export type StringTuple = [number, string?] +/** The result of parsing a MultiaddrInput string */ +export interface MultiaddrInputStringResult { + bytes: Uint8Array + tuples: Tuple[] + path: string | null +} + /** * Allows aborting long-lived operations */ @@ -513,7 +525,7 @@ class DefaultMultiaddr implements Multiaddr { if (addr.length > 0 && addr.charAt(0) !== '/') { throw new Error(`multiaddr "${addr}" must start with a "/"`) } - const { bytes, tuples, path } = codec.fromString(addr) + const { bytes, tuples, path } = codec.fromMultiaddrInputString(addr) this.bytes = bytes this.#tuples = tuples this.#path = path diff --git a/test/codec.spec.ts b/test/codec.spec.ts index 2d5efad6..6f4377cd 100644 --- a/test/codec.spec.ts +++ b/test/codec.spec.ts @@ -19,7 +19,8 @@ describe('codec', () => { describe('.stringTuplesToTuples', () => { const testCases: Array<{ name: string, stringTuples: Array, tuples: Array<[number, Uint8Array?]>, path: string | null }> = [ { name: 'handles non array tuples', stringTuples: [['ip4', '0.0.0.0'], 'utp'], tuples: [[4, Uint8Array.from([0, 0, 0, 0])], [302]], path: null }, - { name: 'handle not null path', stringTuples: [['unix', '/tmp/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')]], path: '/tmp/p2p.sock' } + { name: 'handle not null path', stringTuples: [['unix', '/tmp/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')]], path: '/tmp/p2p.sock' }, + { name: 'should return the 1st path', stringTuples: [['unix', '/tmp/p2p.sock'], ['unix', '/tmp2/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')], [400, convertToBytes(400, '/tmp2/p2p.sock')]], path: '/tmp/p2p.sock' } ] for (const { name, stringTuples, tuples, path } of testCases) { From b1772d65ac8414c09f5a6ebb49511c29cdc653bf Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Thu, 13 Jul 2023 08:31:08 +0700 Subject: [PATCH 3/4] chore: clarify the condition to check for undefined path --- src/codec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codec.ts b/src/codec.ts index a0bb55a0..e907ff9c 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -83,7 +83,7 @@ export function stringTuplesToTuples (stringTuples: Array): O return tuple }) - if (path == null) { + if (path === undefined) { path = null } From 6cdff90d1bf6cac169e6c5fe443b645bc841b250 Mon Sep 17 00:00:00 2001 From: Cayman Date: Fri, 14 Jul 2023 15:39:46 -0400 Subject: [PATCH 4/4] feat: precalculate multiaddr parts --- src/codec.ts | 218 ++++++++++++++++++++------------------------- src/index.ts | 97 +++++--------------- test/codec.spec.ts | 58 +++--------- 3 files changed, 132 insertions(+), 241 deletions(-) diff --git a/src/codec.ts b/src/codec.ts index e907ff9c..fb7ed616 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -3,16 +3,31 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import varint from 'varint' import { convertToBytes, convertToString } from './convert.js' import { getProtocol } from './protocols-table.js' -import type { StringTuple, Tuple, Protocol, MultiaddrInputString, MultiaddrInputStringResult } from './index.js' +import type { StringTuple, Tuple, Protocol } from './index.js' -/** - * string -> [[str name, str addr]... ] - */ -export function stringToStringTuples (str: string): string[][] { - const tuples = [] - const parts = str.split('/').slice(1) // skip first empty elem +export interface MultiaddrParts { + bytes: Uint8Array + string: string + tuples: Tuple[] + stringTuples: StringTuple[] + path: string | null +} + +export function stringToMultiaddrParts (str: string): MultiaddrParts { + str = cleanPath(str) + const tuples: Tuple[] = [] + const stringTuples: StringTuple[] = [] + let path: string | null = null + + const parts = str.split('/').slice(1) if (parts.length === 1 && parts[0] === '') { - return [] + return { + bytes: new Uint8Array(), + string: '/', + tuples: [], + stringTuples: [], + path: null + } } for (let p = 0; p < parts.length; p++) { @@ -20,7 +35,8 @@ export function stringToStringTuples (str: string): string[][] { const proto = getProtocol(part) if (proto.size === 0) { - tuples.push([part]) + tuples.push([proto.code]) + stringTuples.push([proto.code]) // eslint-disable-next-line no-continue continue } @@ -32,85 +48,104 @@ export function stringToStringTuples (str: string): string[][] { // if it's a path proto, take the rest if (proto.path === true) { - tuples.push([ - part, - // should we need to check each path part to see if it's a proto? - // This would allow for other protocols to be added after a unix path, - // however it would have issues if the path had a protocol name in the path - cleanPath(parts.slice(p).join('/')) - ]) + // should we need to check each path part to see if it's a proto? + // This would allow for other protocols to be added after a unix path, + // however it would have issues if the path had a protocol name in the path + path = cleanPath(parts.slice(p).join('/')) + tuples.push([proto.code, convertToBytes(proto.code, path)]) + stringTuples.push([proto.code, path]) break } - tuples.push([part, parts[p]]) + const bytes = convertToBytes(proto.code, parts[p]) + tuples.push([proto.code, bytes]) + stringTuples.push([proto.code, convertToString(proto.code, bytes)]) } - return tuples + return { + string: stringTuplesToString(stringTuples), + bytes: tuplesToBytes(tuples), + tuples, + stringTuples, + path + } } -/** - * [[str name, str addr]... ] -> string - */ -export function stringTuplesToString (tuples: StringTuple[]): string { - const parts: string[] = [] - tuples.map((tup) => { - const proto = protoFromTuple(tup) - parts.push(proto.name) - if (tup.length > 1 && tup[1] != null) { - parts.push(tup[1]) - } - return null - }) +export function bytesToMultiaddrParts (bytes: Uint8Array): MultiaddrParts { + const tuples: Tuple[] = [] + const stringTuples: StringTuple[] = [] + let path: string | null = null - return cleanPath(parts.join('/')) -} + let i = 0 + while (i < bytes.length) { + const code = varint.decode(bytes, i) + const n = varint.decode.bytes ?? 0 -/** - * [[str name, str addr]... ] -> {tuples: [[int code, Uint8Array]... ], path: str} - * The logic to get path is the same to DefaultMultiaddr.getPath() - */ -export function stringTuplesToTuples (stringTuples: Array): Omit { - let path: string | null | undefined - const tuples = stringTuples.map((tup) => { - if (!Array.isArray(tup)) { - tup = [tup] + const p = getProtocol(code) + + const size = sizeForAddr(p, bytes.slice(i + n)) + + if (size === 0) { + tuples.push([code]) + stringTuples.push([code]) + i += n + // eslint-disable-next-line no-continue + continue } - const proto = protoFromTuple(tup) - const tuple: Tuple = (tup.length > 1) ? [proto.code, convertToBytes(proto.code, tup[1])] : [proto.code] - if (path === undefined && proto.path === true) { - path = tuple[1] != null ? convertToString(proto.code, tuple[1]) : null + + const addr = bytes.slice(i + n, i + n + size) + + i += (size + n) + + if (i > bytes.length) { // did not end _exactly_ at buffer.length + throw ParseError('Invalid address Uint8Array: ' + uint8ArrayToString(bytes, 'base16')) } - return tuple - }) - if (path === undefined) { - path = null + // ok, tuple seems good. + tuples.push([code, addr]) + const stringAddr = convertToString(code, addr) + stringTuples.push([code, stringAddr]) + if (p.path === true) { + // should we need to check each path part to see if it's a proto? + // This would allow for other protocols to be added after a unix path, + // however it would have issues if the path had a protocol name in the path + path = stringAddr + break + } } - return { tuples, path } + return { + bytes: Uint8Array.from(bytes), + string: stringTuplesToString(stringTuples), + tuples, + stringTuples, + path + } } /** - * Convert tuples to string tuples - * - * [[int code, Uint8Array]... ] -> [[int code, str addr]... ] + * [[str name, str addr]... ] -> string */ -export function tuplesToStringTuples (tuples: Tuple[]): StringTuple[] { - return tuples.map(tup => { - const proto = protoFromTuple(tup) - if (tup[1] != null) { - return [proto.code, convertToString(proto.code, tup[1])] +function stringTuplesToString (tuples: StringTuple[]): string { + const parts: string[] = [] + tuples.map((tup) => { + const proto = getProtocol(tup[0]) + parts.push(proto.name) + if (tup.length > 1 && tup[1] != null) { + parts.push(tup[1]) } - return [proto.code] + return null }) + + return cleanPath(parts.join('/')) } /** * [[int code, Uint8Array ]... ] -> Uint8Array */ export function tuplesToBytes (tuples: Tuple[]): Uint8Array { - return fromBytes(uint8ArrayConcat(tuples.map((tup) => { - const proto = protoFromTuple(tup) + return uint8ArrayConcat(tuples.map((tup) => { + const proto = getProtocol(tup[0]) let buf = Uint8Array.from(varint.encode(proto.code)) if (tup.length > 1 && tup[1] != null) { @@ -118,13 +153,13 @@ export function tuplesToBytes (tuples: Tuple[]): Uint8Array { } return buf - }))) + })) } /** * For the passed address, return the serialized size */ -export function sizeForAddr (p: Protocol, addr: Uint8Array | number[]): number { +function sizeForAddr (p: Protocol, addr: Uint8Array | number[]): number { if (p.size > 0) { return p.size / 8 } else if (p.size === 0) { @@ -168,56 +203,6 @@ export function bytesToTuples (buf: Uint8Array): Tuple[] { return tuples } -/** - * Uint8Array -> String - */ -export function bytesToString (buf: Uint8Array): string { - const a = bytesToTuples(buf) - const b = tuplesToStringTuples(a) - return stringTuplesToString(b) -} - -/** - * MultiaddrInputString -> MultiaddrInputStringResult - */ -export function parseMultiaddrInputString (str: MultiaddrInputString): MultiaddrInputStringResult { - str = cleanPath(str) - const stringTuples = stringToStringTuples(str) - const { tuples, path } = stringTuplesToTuples(stringTuples) - - return { bytes: tuplesToBytes(tuples), tuples, path } -} - -/** - * MultiaddrInputString -> MultiaddrInputStringResult - */ -export function fromMultiaddrInputString (str: MultiaddrInputString): MultiaddrInputStringResult { - return parseMultiaddrInputString(str) -} - -/** - * Uint8Array -> Uint8Array - */ -export function fromBytes (buf: Uint8Array): Uint8Array { - const err = validateBytes(buf) - if (err != null) { - throw err - } - return Uint8Array.from(buf) // copy -} - -export function validateBytes (buf: Uint8Array): Error | undefined { - try { - bytesToTuples(buf) // try to parse. will throw if breaks - } catch (err: any) { - return err - } -} - -export function isValidBytes (buf: Uint8Array): boolean { - return validateBytes(buf) === undefined -} - export function cleanPath (str: string): string { return '/' + str.trim().split('/').filter((a) => a).join('/') } @@ -225,8 +210,3 @@ export function cleanPath (str: string): string { export function ParseError (str: string): Error { return new Error('Error parsing address: ' + str) } - -export function protoFromTuple (tup: any[]): Protocol { - const proto = getProtocol(tup[0]) - return proto -} diff --git a/src/index.ts b/src/index.ts index f1ec0bd0..a9fee946 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,8 +17,7 @@ import { base58btc } from 'multiformats/bases/base58' import { CID } from 'multiformats/cid' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import varint from 'varint' -import * as codec from './codec.js' +import { bytesToMultiaddrParts, stringToMultiaddrParts, type MultiaddrParts, tuplesToBytes } from './codec.js' import { getProtocol, names } from './protocols-table.js' const inspect = Symbol.for('nodejs.util.inspect.custom') @@ -60,15 +59,10 @@ export interface NodeAddress { port: number } -/** - * Represent a multiaaddr input string - */ -export type MultiaddrInputString = string - /** * These types can be parsed into a {@link Multiaddr} object */ -export type MultiaddrInput = MultiaddrInputString | Multiaddr | Uint8Array | null +export type MultiaddrInput = string | Multiaddr | Uint8Array | null /** * A Resolver is a function that takes a {@link Multiaddr} and resolves it into one @@ -86,13 +80,6 @@ export type Tuple = [number, Uint8Array?] */ export type StringTuple = [number, string?] -/** The result of parsing a MultiaddrInput string */ -export interface MultiaddrInputStringResult { - bytes: Uint8Array - tuples: Tuple[] - path: string | null -} - /** * Allows aborting long-lived operations */ @@ -506,10 +493,10 @@ export function isMultiaddr (value: any): value is Multiaddr { */ class DefaultMultiaddr implements Multiaddr { public bytes: Uint8Array - #string?: string - #tuples?: Tuple[] - #stringTuples?: StringTuple[] - #path?: string | null + #string: string + #tuples: Tuple[] + #stringTuples: StringTuple[] + #path: string | null [symbol]: boolean = true @@ -519,28 +506,28 @@ class DefaultMultiaddr implements Multiaddr { addr = '' } + let parts: MultiaddrParts if (addr instanceof Uint8Array) { - this.bytes = codec.fromBytes(addr) + parts = bytesToMultiaddrParts(addr) } else if (typeof addr === 'string') { if (addr.length > 0 && addr.charAt(0) !== '/') { throw new Error(`multiaddr "${addr}" must start with a "/"`) } - const { bytes, tuples, path } = codec.fromMultiaddrInputString(addr) - this.bytes = bytes - this.#tuples = tuples - this.#path = path + parts = stringToMultiaddrParts(addr) } else if (isMultiaddr(addr)) { // Multiaddr - this.bytes = codec.fromBytes(addr.bytes) // validate + copy buffer + parts = bytesToMultiaddrParts(addr.bytes) } else { throw new Error('addr must be a string, Buffer, or another Multiaddr') } + + this.bytes = parts.bytes + this.#string = parts.string + this.#tuples = parts.tuples + this.#stringTuples = parts.stringTuples + this.#path = parts.path } toString (): string { - if (this.#string == null) { - this.#string = codec.bytesToString(this.bytes) - } - return this.#string } @@ -602,44 +589,22 @@ class DefaultMultiaddr implements Multiaddr { } protos (): Protocol[] { - return this.protoCodes().map(code => Object.assign({}, getProtocol(code))) + return this.#tuples.map(([code]) => Object.assign({}, getProtocol(code))) } protoCodes (): number[] { - const codes: number[] = [] - const buf = this.bytes - let i = 0 - while (i < buf.length) { - const code = varint.decode(buf, i) - const n = varint.decode.bytes ?? 0 - - const p = getProtocol(code) - const size = codec.sizeForAddr(p, buf.slice(i + n)) - - i += (size + n) - codes.push(code) - } - - return codes + return this.#tuples.map(([code]) => code) } protoNames (): string[] { - return this.protos().map(proto => proto.name) + return this.#tuples.map(([code]) => getProtocol(code).name) } tuples (): Array<[number, Uint8Array?]> { - if (this.#tuples == null) { - this.#tuples = codec.bytesToTuples(this.bytes) - } - return this.#tuples } stringTuples (): Array<[number, string?]> { - if (this.#stringTuples == null) { - this.#stringTuples = codec.tuplesToStringTuples(this.tuples()) - } - return this.#stringTuples } @@ -662,7 +627,7 @@ class DefaultMultiaddr implements Multiaddr { const tuples = this.tuples() for (let i = tuples.length - 1; i >= 0; i--) { if (tuples[i][0] === code) { - return new DefaultMultiaddr(codec.tuplesToBytes(tuples.slice(0, i))) + return new DefaultMultiaddr(tuplesToBytes(tuples.slice(0, i))) } } return this @@ -699,26 +664,6 @@ class DefaultMultiaddr implements Multiaddr { } getPath (): string | null { - // on initialization, this.#path is undefined - // after the first call, it is either a string or null - if (this.#path === undefined) { - try { - this.#path = this.stringTuples().filter((tuple) => { - const proto = getProtocol(tuple[0]) - if (proto.path === true) { - return true - } - return false - })[0][1] - - if (this.#path == null) { - this.#path = null - } - } catch { - this.#path = null - } - } - return this.#path } @@ -786,7 +731,7 @@ class DefaultMultiaddr implements Multiaddr { * ``` */ [inspect] (): string { - return `Multiaddr(${codec.bytesToString(this.bytes)})` + return `Multiaddr(${this.#string})` } } diff --git a/test/codec.spec.ts b/test/codec.spec.ts index 6f4377cd..3cf73357 100644 --- a/test/codec.spec.ts +++ b/test/codec.spec.ts @@ -1,49 +1,37 @@ /* eslint-env mocha */ import { expect } from 'aegir/chai' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import varint from 'varint' import * as codec from '../src/codec.js' import { convertToBytes } from '../src/convert.js' +import type { StringTuple, Tuple } from '../src/index.js' describe('codec', () => { - describe('.stringToStringTuples', () => { + describe('.stringToMultiaddrParts', () => { it('throws on invalid addresses', () => { expect( - () => codec.stringToStringTuples('/ip4/0.0.0.0/ip4') + () => codec.stringToMultiaddrParts('/ip4/0.0.0.0/ip4') ).to.throw( /invalid address/ ) }) }) - describe('.stringTuplesToTuples', () => { - const testCases: Array<{ name: string, stringTuples: Array, tuples: Array<[number, Uint8Array?]>, path: string | null }> = [ - { name: 'handles non array tuples', stringTuples: [['ip4', '0.0.0.0'], 'utp'], tuples: [[4, Uint8Array.from([0, 0, 0, 0])], [302]], path: null }, - { name: 'handle not null path', stringTuples: [['unix', '/tmp/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')]], path: '/tmp/p2p.sock' }, - { name: 'should return the 1st path', stringTuples: [['unix', '/tmp/p2p.sock'], ['unix', '/tmp2/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')], [400, convertToBytes(400, '/tmp2/p2p.sock')]], path: '/tmp/p2p.sock' } + describe('.stringToMultiaddrParts', () => { + const testCases: Array<{ name: string, string: string, stringTuples: StringTuple[], tuples: Tuple[], path: string | null }> = [ + { name: 'handles non array tuples', string: '/ip4/0.0.0.0/utp', stringTuples: [[4, '0.0.0.0'], [302]], tuples: [[4, Uint8Array.from([0, 0, 0, 0])], [302]], path: null }, + { name: 'handle not null path', string: '/unix/tmp/p2p.sock', stringTuples: [[400, '/tmp/p2p.sock']], tuples: [[400, convertToBytes(400, '/tmp/p2p.sock')]], path: '/tmp/p2p.sock' } ] - for (const { name, stringTuples, tuples, path } of testCases) { + for (const { name, string, stringTuples, tuples, path } of testCases) { it(name, () => { - expect( - codec.stringTuplesToTuples(stringTuples) - ).to.eql( - { tuples, path } - ) + const parts = codec.stringToMultiaddrParts(string) + expect(parts.stringTuples).to.eql(stringTuples) + expect(parts.tuples).to.eql(tuples) + expect(parts.path).to.eql(path) }) } }) - describe('.tuplesToStringTuples', () => { - it('single element tuples', () => { - expect( - codec.tuplesToStringTuples([[302]]) - ).to.eql( - [[302]] - ) - }) - }) - describe('.bytesToTuples', () => { it('throws on invalid address', () => { expect( @@ -53,26 +41,4 @@ describe('codec', () => { ) }) }) - - describe('.fromBytes', () => { - it('throws on invalid buffer', () => { - expect( - () => codec.fromBytes(uint8ArrayFromString('hello/world')) - ).to.throw() - }) - }) - - describe('.isValidBytes', () => { - it('returns true for valid buffers', () => { - expect( - codec.isValidBytes(Uint8Array.from(varint.encode(302))) - ).to.equal(true) - }) - - it('returns false for invalid buffers', () => { - expect( - codec.isValidBytes(Uint8Array.from(varint.encode(1234))) - ).to.equal(false) - }) - }) })