document url code

This commit is contained in:
SArpnt 2024-03-14 19:58:44 -04:00
parent b0c388efff
commit f1930367e3
Signed by: SArpnt
SSH Key Fingerprint: SHA256:iDMeic8KkqqEsN4wODlgsk1d/oW1ojZ/cu/MEWyfLBw
2 changed files with 39 additions and 14 deletions

View File

@ -9,11 +9,20 @@ const fromchar = Object.fromEntries(Object.entries(tochar).map(([i, v]) => [v, B
// go through 123 bits at a time, into 19 character chunks
// bitIndex from 0 to 7 to trim bits off the input data
// least amount of bits that requires a base 89 string of a specific length
/** least amount of bits that requires a base 89 string of a specific length */
const lbl = Array(20)
.fill(undefined)
.map((v, i) => i && (89n ** BigInt(i - 1)).toString(2).length);
.map((_, i) => i && (89n ** BigInt(i - 1)).toString(2).length);
/**
* converts data into base89, using all the valid characters for a url anchor.
* this allows incredibly small urls, but many of these characters
* break markdown and other common post formatting.
*
* bitIndex is the first bit that into89 will read from and encode,
* and it'll continue until the end of the array.
* use bitIndex if you want to trim less than 8 bits off the data.
*/
function into89(data: Uint8Array, bitIndex = 0): string {
let coded = "";
while (true) {
@ -25,18 +34,17 @@ function into89(data: Uint8Array, bitIndex = 0): string {
bigint += BigInt(!!(data[bitIndex >> 3] & (1 << (bitIndex & 7)))) << BigInt(i);
bitIndex++;
} else {
// length kept being wrong, i gave up on it
//bigint = BigInt.asUintN(123, bigint << BigInt(bitOffset));
// TODO length often wrong, i gave up on it for now
/*
for (const bits of lbl.slice(1).map(x => x - 1)) {
if (bits >= i) {
return coded;
}
coded += tochar[Number(bigint % 89n)];
bigint /= 89n;
}
// unreachable
*/
//for (const bits of lbl.slice(1).map(x => x - 1)) {
// if (bits >= i) {
// return coded;
// }
// coded += tochar[Number(bigint % 89n)];
// bigint /= 89n;
//}
//// unreachable
while (bigint) {
coded += tochar[Number(bigint % 89n)];
bigint /= 89n;
@ -52,8 +60,16 @@ function into89(data: Uint8Array, bitIndex = 0): string {
}
}
/**
* converts data from base89, the opposite of into89.
* the decoded data will be placed at bitIndex in the returned array.
* the length will always be equal or longer than the original data,
* and any extra data will be 0 bits. this is fine for a deflate stream,
* which already encodes the end in the format.
*/
function from89(coded: string, bitIndex = 0 /*, byteUp = true*/): Uint8Array {
// all this code is PROBABLY correct but i'm not sure because into89 length is wrong anyways
//const chunkCount = Math.max(Math.ceil(coded.length / 19) - 1, 0);
//const chunkRem = coded.length - chunkCount * 19;
//const lbla = lbl[chunkRem];

View File

@ -2,7 +2,7 @@ import { deflateSync, inflateSync } from "fflate";
import { from89 } from "./base89.ts";
import type { Song, SongMode } from "../common.ts";
// see smallmode.md
/** see smallmode.md */
const smallmode_table = {
Bytebeat: 0b00000111,
"Signed Bytebeat": 0b00000110,
@ -136,6 +136,15 @@ async function setUrlData({ code, mode, sampleRate }: Song) {
window.location.hash = `#6${base89}`;
}*/
/**
* sampleRate MUST be a 32 bit float within the range [2, 16777215]
* other samplerates in range will automatically round
* samplerates out of the range won't get stored correctly at all
* you can do Math.min(Math.max(Math.fround(sampleRate), 2), 2 ** 24 - 1)
* to get any number within the correct range
*
* this function sets the window hash directly, it doesn't return a string
*/
async function setUrlData({ code, mode, sampleRate }: Song) {
const smallmode = smallmode_table[mode];