valia
Version:
A runtime data validator in TypeScript with advanced type inference, built-in validation functions, and seamless integration for server and client environments.
243 lines (210 loc) • 7.53 kB
text/typescript
import { Issue } from "../utils";
function convertBase16ToBase64(input: string, base64: string, padding: boolean) {
const totalChunksLength = Math.floor(input.length / 6) * 6;
let output = "";
let i = 0;
while (i < totalChunksLength) {
const dec = parseInt(input.slice(i, i + 6), 16);
output += (base64[((dec >> 18) & 63)]
+ base64[((dec >> 12) & 63)]
+ base64[((dec >> 6) & 63)]
+ base64[(dec & 63)]);
i += 6;
}
if (i < input.length) {
const restChunk = input.slice(i, i + 6);
// 143016576 = 00100 01000 01100 10000 10100 00000 = 4 8 12 16 20 0
const leftShift = (143016576 >> (restChunk.length * 5)) & 31;
const dec = parseInt(restChunk, 16) << leftShift;
output += base64[((dec >> 18) & 63)]
+ base64[((dec >> 12) & 63)];
if (leftShift < 12) output += base64[((dec >> 6) & 63)];
if (leftShift < 8) output += base64[(dec & 63)];
}
while (padding && output.length % 4 !== 0) {
output += '=';
}
return (output);
}
function convertBase16ToBase32(input: string, base32: string, padding: boolean = true) {
const totalChunksLength = Math.floor(input.length / 10) * 10;
let output = "";
let i = 0;
while (i < totalChunksLength) {
const decHigh = parseInt(input.slice(i, i + 5), 16);
const decLow = parseInt(input.slice(i + 5, i + 10), 16);
output += base32[((decHigh >> 15) & 31)]
+ base32[((decHigh >> 10) & 31)]
+ base32[((decHigh >> 5) & 31)]
+ base32[(decHigh & 31)]
+ base32[((decLow >> 15) & 31)]
+ base32[((decLow >> 10) & 31)]
+ base32[((decLow >> 5) & 31)]
+ base32[(decLow & 31)];
i += 10;
}
if (i < input.length) {
const restChunk = input.slice(i, i + 5);
// 4469248 = 00100 01000 01100 10000 00000 = 4 8 12 16 0
const leftShift = (4469248 >> (restChunk.length * 5)) & 31;
const decHigh = parseInt(restChunk, 16) << leftShift;
output += base32[((decHigh >> 15) & 31)]
+ base32[((decHigh >> 10) & 31)];
if (leftShift < 12) {
output += base32[((decHigh >> 5) & 31)]
+ base32[(decHigh & 31)];
}
}
if (i + 5 < input.length) {
const restChunk = input.slice(i + 5, i + 10);
// 4469248 = 00100 01000 01100 10000 00000 = 4 8 12 16 0
const leftShift = (4469248 >> (restChunk.length * 5)) & 31;
const decLow = parseInt(restChunk, 16) << leftShift;
output += base32[((decLow >> 15) & 31)]
+ base32[((decLow >> 10) & 31)];
if (leftShift < 12) output += base32[((decLow >> 5) & 31)];
if (leftShift < 8) output += base32[(decLow & 31)];
}
while (padding && output.length % 8 !== 0) {
output += '=';
}
return (output);
}
function convertBase64ToBase16(input: string, base64: string) {
if (input.endsWith("=")) input = input.slice(0, input.indexOf("="));
const totalChunksLength = Math.floor(input.length / 4) * 4;
const base16 = "0123456789ABCDEF";
let output = "";
let i = 0;
while (i < totalChunksLength) {
const dec = (base64.indexOf(input[i]) << 18)
| (base64.indexOf(input[i + 1]) << 12)
| (base64.indexOf(input[i + 2]) << 6)
| base64.indexOf(input[i + 3]);
output += base16[((dec >> 20) & 15)]
+ base16[((dec >> 16) & 15)]
+ base16[((dec >> 12) & 15)]
+ base16[((dec >> 8) & 15)]
+ base16[((dec >> 4) & 15)]
+ base16[(dec & 15)];
i += 4;
}
if (i < input.length) {
const rest = input.slice(i);
const restLength = rest.length;
const dec = ((base64.indexOf(rest[0]) << 18)
| (rest[1] ? base64.indexOf(rest[1]) << 12 : 0)
| (rest[2] ? base64.indexOf(rest[2]) << 6 : 0)
| (rest[3] ? base64.indexOf(rest[3]) : 0));
output += base16[((dec >> 20) & 15)]
+ base16[((dec >> 16) & 15)];
if (restLength > 2) {
output += base16[((dec >> 12) & 15)]
+ base16[((dec >> 8) & 15)];
}
if (restLength > 3) {
output += base16[((dec >> 4) & 15)]
+ base16[(dec & 15)];
}
}
return (output);
}
function convertBase32ToBase16(input: string, base32: string) {
if (input.endsWith("=")) input = input.slice(0, input.indexOf("="));
const totalChunksLength = Math.floor(input.length / 8) * 8;
const base16 = "0123456789ABCDEF";
let output = "";
let i = 0;
while (i < totalChunksLength) {
const dec = (base32.indexOf(input[i]) << 15)
| (base32.indexOf(input[i + 1]) << 10)
| (base32.indexOf(input[i + 2]) << 5)
| base32.indexOf(input[i + 3]);
output += base16[((dec >> 16) & 15)]
+ base16[((dec >> 12) & 15)]
+ base16[((dec >> 8) & 15)]
+ base16[((dec >> 4) & 15)]
+ base16[(dec & 15)];
i += 4;
}
if (i < input.length) {
const rest = input.slice(i);
const restLength = rest.length;
const dec = ((base32.indexOf(rest[0]) << 15)
| (rest[1] ? base32.indexOf(rest[1]) << 10 : 0)
| (rest[2] ? base32.indexOf(rest[2]) << 5 : 0)
| (rest[3] ? base32.indexOf(rest[3]) : 0));
output += base16[((dec >> 16) & 15)]
+ base16[((dec >> 12) & 15)];
if (restLength > 1) {
output += base16[((dec >> 8) & 15)]
+ base16[((dec >> 4) & 15)];
}
if (restLength > 3) {
output += base16[(dec & 15)]
if (i + 5 >= input.length) {
output += base16[0];
}
}
}
if (i + 5 < input.length) {
const rest = input.slice(i + 5);
const restLength = rest.length;
const dec = ((base32.indexOf(rest[0]) << 15)
| (rest[1] ? base32.indexOf(rest[1]) << 10 : 0)
| (rest[2] ? base32.indexOf(rest[2]) << 5 : 0)
| (rest[3] ? base32.indexOf(rest[3]) : 0));
output += base16[((dec >> 16) & 15)]
+ base16[((dec >> 12) & 15)]
+ base16[((dec >> 8) & 15)];
if (restLength > 2) {
output += base16[((dec >> 4) & 15)]
+ base16[(dec & 15)];
}
}
return (output);
}
export function base16ToBase64(input: string, to: "B64" | "B64URL" = "B64", padding: boolean = true) {
if (to === "B64") {
const base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
return (convertBase16ToBase64(input, base64, padding));
} else if (to === "B64URL") {
const base64Url = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
return (convertBase16ToBase64(input, base64Url, padding));
} else {
throw new Issue("Parameters", "The base64 type of the parameter 'to' is unknown.");
}
}
export function base16ToBase32(input: string, to: "B16" | "B16HEX" = "B16", padding: boolean = true) {
if (to === "B16") {
const base32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
return (convertBase16ToBase32(input, base32, padding));
} else if (to === "B16HEX") {
const base32Hex = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
return (convertBase16ToBase32(input, base32Hex, padding));
} else {
throw new Issue("Parameters", "The base32 type of the parameter 'to' is unknown.");
}
}
export function base64ToBase16(input: string, from: "B64" | "B64URL" = "B64") {
if (from === "B64") {
const base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
return (convertBase64ToBase16(input, base64));
} else if (from === "B64URL") {
const base64Url = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
return (convertBase64ToBase16(input, base64Url));
} else {
throw new Issue("Parameters", "The base64 type of the parameter 'from' is unknown.");
}
}
export function base32ToBase16(input: string, from: "B16" | "B16HEX" = "B16") {
if (from === "B16") {
const base32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
return (convertBase32ToBase16(input, base32));
} else if (from === "B16HEX") {
const base32Hex = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
return (convertBase32ToBase16(input, base32Hex));
} else {
throw new Issue("Parameters", "The base32 type of the parameter 'from' is unknown.");
}
}