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', () => {