Skip to content

Instantly share code, notes, and snippets.

@guest271314
Last active February 17, 2025 16:19
Show Gist options
  • Select an option

  • Save guest271314/56e96bcb5e6965ac62e3ab890d539a6d to your computer and use it in GitHub Desktop.

Select an option

Save guest271314/56e96bcb5e6965ac62e3ab890d539a6d to your computer and use it in GitHub Desktop.
Uint32Array to Uint8Array, Uint8Array to Uint32Array

In some environments and contexts the processing model is based on UTF-8. In those same environments the processing model can be strings and not ArrayBuffer or TypedArray.

When the data includes Uint32Array it could become necessary to convert Uint32Array to Uint8Array, Uint32Array to Uint8Array.

Here are some approaches I have used to convert between Uint32Array (4 bytes per element) and Uint8Array (1 byte per element).

See 23.2 TypedArray Objects.

Encode the length of 1 MB of JSON into a Uint32Array

// Given 1 MB of JSON encode data length
let data = Array(209715);
let json = JSON.stringify(data);
console.log(json.length); // 1048576

Uint32Array constructor

let uint32 = new Uint32Array([json.length]); // uint32[0] 1048576

DataView

let ab = new ArrayBuffer(Uint32Array.BYTES_PER_ELEMENT);
let view = new DataView(ab);
view.setUint32(0, json.length, true); // Little endian

When we have to use Uint8Array (0 to 255 values, size in bytes 1) to encode Uint32Array (0 to 4294967295 values, size in bytes 4) our Uint8Array will contain [0, 0, 16, 0].

let uint8 = new Uint8Array(uint32.buffer);
// Uint8Array(4) [0, 0, 16, 0, buffer: ArrayBuffer(4), byteLength: 4, byteOffset: 0, length: 4, Symbol(Symbol.toStringTag): 'Uint8Array']

Get the Uint32Array value

DataView
// Get the value
let length = view.getUint32(0, true);

Bitwise operators working on Uint8Array indexes

let uint32ValueFromUint8 = (uint8[3] << 24) | (uint8[2] << 16) | (uint8[1] << 8) | (uint8[0]); // 1048576

Set Uint8Array to Uint32Array

// Get value at index [0]
let uint32 = Uint32Array.of(
    [...uint8]
      .reduceRight((a, b, index) => a << (index * 8) | b << ((index * 8) - 8)),
  );

Long form

// https://stackoverflow.com/a/58288413
let header = new Uint32Array([
  ((uint32) =>
    (uint32[3] << 24) |
    (uint32[2] << 16) |
    (uint32[1] << 8) |
    (uint32[0]))(Array.from({
    length: 4,
  }, (_, index) => (uint8.length >> (index * 8)) & 0xff)),
]);

Send Uint32Array containing data length as Uint8Array followed by data

const data = new Uint8Array([...new Uint8Array(uint32.buffer), ...uint8]);
stdout.write(data.buffer, 0, data.length); 

Read Uint32Array from Uint8Array

We're dealing with a JSON string (UTF-8) here, encode to TypedArray Uint8Array first

function encodeMessage(str) {
  return new Uint8Array([...str].map((s) => s.codePointAt()));
}
const data = encodeMessage(stdin.read()); 
const view = new DataView(data.subarray(0, 4).buffer);
const length = view.getUint32(0, true);
const message = data.subarray(4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment