vanillaaont
Version:
simple all-or-nothing transform in nothing but vanilla js
102 lines (95 loc) • 3.3 kB
JavaScript
/**
The name of this file is a result of this transform seeming to somehow compress the input
but I do not know how.
What I mean is...the transform here seems to produce a result that contains less source characters
than are actually in the source, and yet perfectly reconstructrs the source.
**/
;
{
const vanillaaont = {
T,TU,rotate_left_by, rotate_right_by
};
const alph = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const dec = "0123456789";
const twomore = "/+!";
const alphabet = alph + dec + alph.toLowerCase() + twomore;
const pad = "!";
const initial_rotate = 13;
const rotates = alphabet.
split('').
reduce( (m,c,i) => ( m[c] = i+1, m ), {} );
try { Object.assign( self, { vanillaaont } ); } catch(e) { module.exports = vanillaaont; }
function T( m ) {
m = Array.from(m);
m.reverse();
let tail_start = m.indexOf('=');
let head = m;
let tail = [];
if ( tail_start >= 0 ) {
head = m.slice(0, tail_start);
tail = m.slice(tail_start);
}
m = pad_to_multiple( 65, pad, head );
const b = Array.from(m);
let i = -1;
while( true ) {
const mc = b[i+1];
const rotate_amount = i >= 0 ? rotates[mc] : initial_rotate;
console.log(i+1, mc, `rotating from ${i+2} by ${rotate_amount}`);
if ( ! rotate_amount ) {
throw new TypeError(`This string is not in base 64. We only know how to interpret these symbols: ${alphabet}. You provided this: "${mc}"` );
}
if ( i+2 < m.length - 65 ) {
const rot_sec = rotate_left_by( rotate_amount, b.slice( i+2, i+67 ) );
b.splice( i+2, 65, ...rot_sec );
} else {
break;
}
i+=1;
}
b.push(...tail);
return b.join('');
}
function TU( m ) {
m = Array.from(m);
const tail_count = m.filter( mc => mc == "=" ).length;
const b = Array.from(m);
let j = m.length-66;
while( j > 0 ) {
const mc = b[j-1];
const rotate_amount = j >= 2 ? rotates[mc] : initial_rotate;
console.log(j-1, mc, `rotating from ${j} by ${rotate_amount}`);
if ( ! rotate_amount ) {
throw new TypeError(`This string is not in base 64. We only know how to interpret these symbols: ${alphabet}. You provided this: "${mc}"` );
}
const rot_sec = rotate_right_by( rotate_amount, b.slice( j, j+65 ) );
b.splice( j, 65, ...rot_sec );
j -= 1;
}
const result = b.filter( mc => mc !== '!' );
result.push( ...Array(tail_count+1).join('=') );
result.reverse();
return result.join('');
}
function rotate_right_by( amount, array ) {
let head = array.slice( array.length - amount );
const tail = array.slice(0,array.length - amount);
head = head.concat(tail);
return head;
}
function rotate_left_by( amount, array ) {
let head = array.slice( amount );
const tail = array.slice(0,amount);
head = head.concat(tail);
return head;
}
function pad_to_multiple( multiplier, pad_char, array ) {
const padding_required = multiplier - (array.length % multiplier);
let padded = Array.from(array);
if ( padding_required ) {
const padding = new Array( padding_required + 1 ).join(pad_char).split('');
padded = padded.concat( padding );
}
return padded;
}
}