@@ -117,12 +117,12 @@ export function rend(coin: coin): string {
117117 case 't' :
118118 if ( coin . aura [ 1 ] === 'a' ) {
119119 if ( coin . aura [ 2 ] === 's' ) {
120- return ' coin.atom' ; //TODO fromCord
120+ return cordToString ( coin . atom ) ;
121121 } else {
122- return '~.' + ' coin.atom' ; //TODO fromCord
122+ return '~.' + cordToString ( coin . atom ) ;
123123 }
124124 } else {
125- return '~~' + 'coin.atom' ; //TODO fromCord(wood (coin.atom))
125+ return '~~' + encodeString ( cordToString ( coin . atom ) ) ;
126126 }
127127 default :
128128 return zco ( coin . atom ) ;
@@ -158,6 +158,52 @@ function wack(str: string) {
158158 return str . replaceAll ( '~' , '~~' ) . replaceAll ( '_' , '~-' ) ;
159159}
160160
161+ // encodeString(): encode string into @ta-safe format
162+ //
163+ // using logic from +wood.
164+ // for example, 'some Chars!' becomes '~.some.~43.hars~21.'
165+ // this is url-safe encoding for arbitrary strings.
166+ //
167+ export function encodeString ( string : string ) {
168+ let out = '' ;
169+ for ( let i = 0 ; i < string . length ; i += 1 ) {
170+ const char = string [ i ] ;
171+ let add = '' ;
172+ switch ( char ) {
173+ case ' ' :
174+ add = '.' ;
175+ break ;
176+ case '.' :
177+ add = '~.' ;
178+ break ;
179+ case '~' :
180+ add = '~~' ;
181+ break ;
182+ default : {
183+ const codePoint = string . codePointAt ( i ) ;
184+ if ( ! codePoint ) break ;
185+ // js strings are encoded in UTF-16, so 16 bits per character.
186+ // codePointAt() reads a _codepoint_ at a character index, and may
187+ // consume up to two js string characters to do so, in the case of
188+ // 16 bit surrogate pseudo-characters. here we detect that case, so
189+ // we can advance the cursor to skip past the additional character.
190+ if ( codePoint > 0xffff ) i += 1 ;
191+ if (
192+ ( codePoint >= 97 && codePoint <= 122 ) || // a-z
193+ ( codePoint >= 48 && codePoint <= 57 ) || // 0-9
194+ char === '-'
195+ ) {
196+ add = char ;
197+ } else {
198+ add = `~${ codePoint . toString ( 16 ) } .` ;
199+ }
200+ }
201+ }
202+ out += add ;
203+ }
204+ return out ;
205+ }
206+
161207const UW_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-~' ;
162208function blend ( bits : number , alphabet : string , atom : bigint ) : string {
163209 if ( atom === 0n ) return alphabet [ 0 ] ;
@@ -176,3 +222,22 @@ function split(str: string, group: number): string {
176222 return str . replace ( new RegExp ( `(?=(?:.{${ group } })+$)(?!^)` , 'g' ) , '.' ) ;
177223}
178224
225+ function cordToString ( atom : bigint ) : string {
226+ return new TextDecoder ( 'utf-8' ) . decode ( atomToByteArray ( atom ) . reverse ( ) ) ;
227+ } ;
228+
229+ //NOTE from nockjs' bigIntToByteArray
230+ //REVIEW original produced [0] for 0n... probably not correct in our contexts!
231+ function atomToByteArray ( atom : bigint ) : Uint8Array {
232+ if ( atom === 0n ) return new Uint8Array ( 0 ) ;
233+ const hexString = atom . toString ( 16 ) ;
234+ const paddedHexString = hexString . length % 2 === 0 ? hexString : '0' + hexString ;
235+ const arrayLength = paddedHexString . length / 2 ;
236+ const int8Array = new Uint8Array ( arrayLength ) ;
237+ for ( let i = 0 ; i < paddedHexString . length ; i += 2 ) {
238+ const hexSubstring = paddedHexString . slice ( i , i + 2 ) ;
239+ const signedInt = ( parseInt ( hexSubstring , 16 ) << 24 ) >> 24 ;
240+ int8Array [ ( i / 2 ) ] = signedInt ;
241+ }
242+ return int8Array ;
243+ }
0 commit comments