import { convertToBytes , convertToString } from './convert.js' ; import { getProtocol } from './protocols-table.js' ; import varint from 'varint' ; import { concat as uint8ArrayConcat } from 'uint8arrays/concat' ; import { toString as uint8ArrayToString } from 'uint8arrays/to-string' ; import type { Protocol } from './protocols-table.js' ; /**
 * string -> [[str name, str addr]... ]
 */ export function stringToStringTuples ( str ) { const tuples = [ ] ; const parts = str . split ( '/' ) . slice ( 1 ) ; if ( parts . length === 1 && parts [ 0 ] === '' ) { return [ ] ; } for ( let p = 0 ; p < parts . length ; p ++ ) { const part = parts [ p ] ; const proto = getProtocol ( part ) ; if ( proto . size === 0 ) { tuples . push ( [ part ] ) ; continue ; } p ++ ; if ( p >= parts . length ) { throw ParseError ( 'invalid address: ' + str ) ; } if ( proto . path === true ) { tuples . push ( [ part , cleanPath ( parts . slice ( p ) . join ( '/' ) ) ] ) ; break ; } tuples . push ( [ part , parts [ p ] ] ) ; } return tuples ; } /**
 * [[str name, str addr]... ] -> string
 */ export function stringTuplesToString ( tuples ) { const parts = [ ] ; tuples . map ( ( tup ) => { const proto = protoFromTuple ( tup ) ; parts . push ( proto . name ) ; if ( tup . length > 1 && tup [ 1 ] != null ) { parts . push ( tup [ 1 ] ) ; } return null ; } ) ; return cleanPath ( parts . join ( '/' ) ) ; } /**
 * [[str name, str addr]... ] -> [[int code, Uint8Array]... ]
 */ export function stringTuplesToTuples ( tuples ) { return tuples . map ( ( tup ) => { if ( ! Array . isArray ( tup ) ) { tup = [ tup ] ; } const proto = protoFromTuple ( tup ) ; if ( tup . length > 1 ) { return [ proto . code , convertToBytes ( proto . code , tup [ 1 ] ) ] ; } return [ proto . code ] ; } ) ; } /**
 * Convert tuples to string tuples
 *
 * [[int code, Uint8Array]... ] -> [[int code, str addr]... ]
 */ export function tuplesToStringTuples ( tuples ) { return tuples . map ( tup => { const proto = protoFromTuple ( tup ) ; if ( tup [ 1 ] != null ) { return [ proto . code , convertToString ( proto . code , tup [ 1 ] ) ] ; } return [ proto . code ] ; } ) ; } /**
 * [[int code, Uint8Array ]... ] -> Uint8Array
 */ export function tuplesToBytes ( tuples ) { return fromBytes ( uint8ArrayConcat ( tuples . map ( ( tup ) => { const proto = protoFromTuple ( tup ) ; let buf = Uint8Array . from ( varint . encode ( proto . code ) ) ; if ( tup . length > 1 && tup [ 1 ] != null ) { buf = uint8ArrayConcat ( [ buf , tup [ 1 ] ] ) ; } return buf ; } ) ) ) ; } export function sizeForAddr ( p , addr ) { if ( p . size > 0 ) { return p . size / 8 ; } else if ( p . size === 0 ) { return 0 ; } else { const size = varint . decode ( addr ) ; return size + varint . decode . bytes ; } } export function bytesToTuples ( buf ) { const tuples = [ ] ; let i = 0 ; while ( i < buf . length ) { const code = varint . decode ( buf , i ) ; const n = varint . decode . bytes ; const p = getProtocol ( code ) ; const size = sizeForAddr ( p , buf . slice ( i + n ) ) ; if ( size === 0 ) { tuples . push ( [ code ] ) ; i += n ; continue ; } const addr = buf . slice ( i + n , i + n + size ) ; i += ( size + n ) ; if ( i > buf . length ) { throw ParseError ( 'Invalid address Uint8Array: ' + uint8ArrayToString ( buf , 'base16' ) ) ; } tuples . push ( [ code , addr ] ) ; } return tuples ; } /**
 * Uint8Array -> String
 */ export function bytesToString ( buf ) { const a = bytesToTuples ( buf ) ; const b = tuplesToStringTuples ( a ) ; return stringTuplesToString ( b ) ; } /**
 * String -> Uint8Array
 */ export function stringToBytes ( str ) { str = cleanPath ( str ) ; const a = stringToStringTuples ( str ) ; const b = stringTuplesToTuples ( a ) ; return tuplesToBytes ( b ) ; } /**
 * String -> Uint8Array
 */ export function fromString ( str ) { return stringToBytes ( str ) ; } /**
 * Uint8Array -> Uint8Array
 */ export function fromBytes ( buf ) { const err = validateBytes ( buf ) ; if ( err != null ) { throw err ; } return Uint8Array . from ( buf ) ; } export function validateBytes ( buf ) { try { bytesToTuples ( buf ) ; } catch ( err ) { return err ; } } export function isValidBytes ( buf ) { return validateBytes ( buf ) === undefined ; } export function cleanPath ( str ) { return '/' + str . trim ( ) . split ( '/' ) . filter ( ( type { any } a ) => a ) . join ( '/' ) ; } export function ParseError ( str ) { return new Error ( 'Error parsing address: ' + str ) ; } export function protoFromTuple ( tup ) { const proto = getProtocol ( tup [ 0 ] ) ; return proto ; }