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).
// Given 1 MB of JSON encode data length
let data = Array(209715);
let json = JSON.stringify(data);
console.log(json.length); // 1048576
let uint32 = new Uint32Array([json.length]); // uint32[0] 1048576
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 value
let length = view.getUint32(0, true);
let uint32ValueFromUint8 = (uint8[3] << 24) | (uint8[2] << 16) | (uint8[1] << 8) | (uint8[0]); // 1048576
// 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)),
]);
const data = new Uint8Array([...new Uint8Array(uint32.buffer), ...uint8]);
stdout.write(data.buffer, 0, data.length);
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);