char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
44fe2c6
main
1import { 2ArrayPrototypeJoin as join , 3ArrayPrototypePush as push , 4String , 5StringPrototypeSlice as slice , 6uncurryThis , 7} from "ext:core/primordials" ; 8import { createException } from "./events.js" ; 9import { array , required , string } from "./idl.js" ; 10 11const alphabet = 12"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; 13const charCode = uncurryThis ( String . prototype . charCodeAt ); 14const fromCharCode = String . fromCharCode ; 15function invalidCharacter () :Error { 16return createException ({ 17message :"The string contains characters outside the Latin1 range." , 18name :"InvalidCharacterError" , 19}) as Error ; 20} 21function sextet ( code :number ) :number { 22if ( code >= 65 && code <= 90 ) return code - 65 ; 23if ( code >= 97 && code <= 122 ) return code - 71 ; 24if ( code >= 48 && code <= 57 ) return code + 4 ; 25if ( code === 43 ) return 62 ; 26if ( code === 47 ) return 63 ; 27return - 1 ; 28} 29 30const api = { 31btoa ( data :unknown ) :string { 32required ( arguments . length , 1 ); 33data = string ( data ); 34const output = array < string >(); 35let chunk = "" ; 36for ( let index = 0 ; index < ( data as string ). length ; index += 3 ) { 37const a = charCode ( data as string , index ); 38const b = index + 1 < ( data as string ). length 39 ?charCode ( data as string , index + 1 ) 40 :- 1 ; 41const c = index + 2 < ( data as string ). length 42 ?charCode ( data as string , index + 2 ) 43 :- 1 ; 44if ( a > 255 || b > 255 || c > 255 ) throw invalidCharacter (); 45chunk += alphabet [ a >> 2 ]; 46chunk += alphabet [(( a & 3 ) << 4 ) | ( b < 0 ?0 :b >> 4 )]; 47chunk += b < 0 48 ?"==" 49 :c < 0 50 ?alphabet [( b & 15 ) << 2 ] + "=" 51 :alphabet [(( b & 15 ) << 2 ) | ( c >> 6 )] + alphabet [ c & 63 ]; 52if ( chunk . length >= 4096 ) { 53push ( output , chunk ); 54chunk = "" ; 55} 56} 57if ( chunk ) push ( output , chunk ); 58return join ( output , "" ); 59}, 60 61atob ( data :unknown ) :string { 62required ( arguments . length , 1 ); 63data = string ( data ); 64const inputParts = array < string >(); 65for ( let index = 0 ; index < ( data as string ). length ; index ++ ) { 66const code = charCode ( data as string , index ); 67if ( 68code === 9 || code === 10 || code === 12 || code === 13 || code === 32 69) { 70continue ; 71} 72push ( inputParts , ( data as string )[ index ]); 73} 74let input = join ( inputParts , "" ); 75const length = input . length ; 76if ( 77length % 4 === 0 && length >= 2 && 78charCode ( input , length - 1 ) === 61 && 79charCode ( input , length - 2 ) === 61 80) { 81input = slice ( input , 0 , length - 2 ); 82} else if ( length % 4 === 0 && charCode ( input , length - 1 ) === 61 ) { 83input = slice ( input , 0 , length - 1 ); 84} 85const remainder = input . length % 4 ; 86if ( remainder === 1 ) throw invalidCharacter (); 87const values = array < number >(); 88for ( let index = 0 ; index < input . length ; index ++ ) { 89const value = sextet ( charCode ( input , index )); 90if ( value < 0 ) throw invalidCharacter (); 91values [ index ] = value ; 92} 93const output = array < string >(); 94let chunk = "" ; 95let index = 0 ; 96for (; index + 3 < values . length ; index += 4 ) { 97chunk += fromCharCode ( 98( values [ index ] << 2 ) | ( values [ index + 1 ] >> 4 ), 99(( values [ index + 1 ] & 15 ) << 4 ) | ( values [ index + 2 ] >> 2 ), 100(( values [ index + 2 ] & 3 ) << 6 ) | values [ index + 3 ], 101); 102if ( chunk . length >= 4096 ) { 103push ( output , chunk ); 104chunk = "" ; 105} 106} 107if ( remainder === 2 ) { 108chunk += fromCharCode (( values [ index ] << 2 ) | ( values [ index + 1 ] >> 4 )); 109} else if ( remainder === 3 ) { 110chunk += fromCharCode ( 111( values [ index ] << 2 ) | ( values [ index + 1 ] >> 4 ), 112(( values [ index + 1 ] & 15 ) << 4 ) | ( values [ index + 2 ] >> 2 ), 113); 114} 115if ( chunk ) push ( output , chunk ); 116return join ( output , "" ); 117}, 118}; 119const { atob, btoa} = api ; 120export { atob , btoa };