Skip to content

Instantly share code, notes, and snippets.

@shalvah
Last active January 20, 2022 14:08
Show Gist options
  • Select an option

  • Save shalvah/46573b7c18b772ac6b4fe1bd7da3d878 to your computer and use it in GitHub Desktop.

Select an option

Save shalvah/46573b7c18b772ac6b4fe1bd7da3d878 to your computer and use it in GitHub Desktop.

Revisions

  1. shalvah revised this gist Jan 18, 2022. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion image.html
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,11 @@
    <canvas id="canvas"></canvas>

    <script>
    // PS: You can run this code in Node.js too, just use this canvas polyfill - https://www.npmjs.com/package/canvas.


    // What we need is an array of bytes, but I prefer working with the hex string
    // because in real life, that's what you're more likely to get.
    // because in real life, that's what you're more likely to get.
    const serializedString = "ff0000ff010000ff00ff00ff000500ff000068ff006500ff6c0000ff6c0000ff006f00ffff0000ff000100ff00ff00ff000600ff00006eff000065ff007300ff007" +
    "400ff000065ff000064ffff0000ff010000ff00ff00ff060000ff00006eff650000ff007300ff000074ff006500ff000064ff00ff00ff050000ff007700ff006f00" +
    "ff000072ff00006cff000064ff";
  2. shalvah revised this gist Jan 18, 2022. No changes.
  3. shalvah revised this gist Jan 18, 2022. No changes.
  4. shalvah created this gist Jan 18, 2022.
    100 changes: 100 additions & 0 deletions format.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,100 @@
    // Note: this uses Node.js' `Buffer`, so it might not work in the browser
    // You can use a polyfill or write yours.

    const RED = [0xFF, 0, 0, 0xFF]; // R, G, B, A
    const GREEN = [0, 0xFF, 0, 0xFF];

    function serialize(val, outputBytes = []) {
    if (typeof val === "string") {
    serializeString(val, outputBytes);
    } else {
    serializeObject(val, outputBytes);
    }

    return outputBytes;
    }

    function wrapInRGBA(value) {
    const rgba = [0, 0, 0, 255];
    const indexToUse = Math.floor(Math.random() * 3);
    rgba[indexToUse] = value;
    return rgba;
    }

    function serializeObject(obj, outputBytes = []) {
    const keys = Object.keys(obj);
    outputBytes.push(...RED);
    outputBytes.push(...wrapInRGBA(keys.length));

    keys.forEach((key) => {
    serialize(key, outputBytes);
    serialize(obj[key], outputBytes);
    });

    return outputBytes;
    }


    function serializeString(str, outputBytes = []) {
    outputBytes.push(...GREEN);
    outputBytes.push(...wrapInRGBA(str.length));
    for (let i = 0; i < str.length; i++) {
    outputBytes.push(...wrapInRGBA(str.charCodeAt(i)));
    }

    return outputBytes;
    }

    function parseFromString(serializedString) {
    return Buffer.from(serializedString, "hex");
    }

    function deserialize(buffer, start = 0) {
    let original;
    let [type, nextIndex] = getNextFourBytes(buffer, start);
    if (Array.from(type).toString() === RED.toString()) {
    original = {};
    let keyCount;
    [keyCount, nextIndex] = getTruthByte(buffer, nextIndex);
    while (keyCount--) {
    let key, value;
    [key, nextIndex] = deserialize(buffer, nextIndex);
    [value, nextIndex] = deserialize(buffer, nextIndex);
    original[key] = value;
    }
    } else if (Array.from(type).toString() === GREEN.toString()) {
    let length;
    [length, nextIndex] = getTruthByte(buffer, nextIndex);
    const characters = [];
    for (let i = 0; i < length; i++) {
    [character, nextIndex] = getTruthByte(buffer, nextIndex);
    characters.push(character);
    }
    original = characters.map(v => String.fromCharCode(v)).join("");
    }

    return [original, nextIndex];
    }

    function getNextFourBytes(buffer, start) {
    return [buffer.slice(start, start + 4), start + 4];
    }

    function getTruthByte(buffer, start) {
    const [slice, nextIndex] = getNextFourBytes(buffer, start);
    return [Array.from(slice).find(v => v != 0) || 0, nextIndex];
    }

    const obj = {hello: {nested: {nested: "world"}}};
    const serialized = serialize(obj);
    console.log(serialized);
    const {Buffer} = require("buffer");
    const serializedString = Buffer.from(serialized).toString("hex");
    console.log(serializedString);
    console.log(Buffer.from(serialized).toString("utf8"));

    const buffer = parseFromString(serializedString);
    const [deserialized] = deserialize(buffer);
    console.log(deserialized);


    31 changes: 31 additions & 0 deletions image.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    <canvas id="canvas"></canvas>

    <script>
    // What we need is an array of bytes, but I prefer working with the hex string
    // because in real life, that's what you're more likely to get.
    const serializedString = "ff0000ff010000ff00ff00ff000500ff000068ff006500ff6c0000ff6c0000ff006f00ffff0000ff000100ff00ff00ff000600ff00006eff000065ff007300ff007" +
    "400ff000065ff000064ffff0000ff010000ff00ff00ff060000ff00006eff650000ff007300ff000074ff006500ff000064ff00ff00ff050000ff007700ff006f00" +
    "ff000072ff00006cff000064ff";
    const numberOfBytes = serializedString.length / 2;

    // But this means we have to convert the hex byte stream to an array first!
    const serializedIntArray = new Uint8Array(numberOfBytes);
    for (let i = 0; i < numberOfBytes; i++) {
    const currentByteAsHexString = serializedString[i * 2] + serializedString[(i * 2) + 1];
    const currentByteAsInt = parseInt(currentByteAsHexString, 16);
    serializedIntArray[i] = currentByteAsInt;
    }

    // Now we can draw the image
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    const height = 100;
    const imageData = ctx.createImageData(numberOfBytes/4, height);
    for (let i = 0; i < numberOfBytes; i++) {
    for (let h = 0; h < height; h++) {
    imageData.data[i + numberOfBytes * h] = serializedIntArray[i];
    }
    }
    ctx.putImageData(imageData, 0, 0);
    </script>