javascript
examples
examples.js⚡javascript
/**
* 6.4 TypedArrays and Binary Data - Examples
*/
// ============================================
// ARRAYBUFFER BASICS
// ============================================
console.log('=== ArrayBuffer Basics ===');
// Create a 16-byte buffer
const buffer = new ArrayBuffer(16);
console.log('Buffer byte length:', buffer.byteLength);
// ArrayBuffer is just raw bytes - need views to access
console.log('Buffer:', buffer); // ArrayBuffer { byteLength: 16 }
// ============================================
// TYPEDARRAY CREATION
// ============================================
console.log('\n=== TypedArray Creation ===');
// From length (initialized to zeros)
const zeros = new Uint8Array(4);
console.log('Zeros:', zeros); // Uint8Array [0, 0, 0, 0]
// From array
const fromArray = new Int16Array([1, 2, 3, 4, 5]);
console.log('From array:', fromArray);
// From ArrayBuffer
const buf = new ArrayBuffer(8);
const uint8View = new Uint8Array(buf);
const uint16View = new Uint16Array(buf);
const uint32View = new Uint32Array(buf);
console.log('Same buffer, different views:');
console.log(' Uint8Array length:', uint8View.length); // 8
console.log(' Uint16Array length:', uint16View.length); // 4
console.log(' Uint32Array length:', uint32View.length); // 2
// ============================================
// SHARED BUFFER DEMONSTRATION
// ============================================
console.log('\n=== Shared Buffer ===');
const sharedBuf = new ArrayBuffer(4);
const bytes = new Uint8Array(sharedBuf);
const ints = new Uint32Array(sharedBuf);
// Set bytes individually
bytes[0] = 0x12;
bytes[1] = 0x34;
bytes[2] = 0x56;
bytes[3] = 0x78;
console.log(
'Bytes:',
Array.from(bytes).map((b) => b.toString(16))
);
console.log('As Uint32:', ints[0].toString(16)); // Depends on endianness
// ============================================
// TYPEDARRAY METHODS
// ============================================
console.log('\n=== TypedArray Methods ===');
const arr = new Uint8Array([10, 20, 30, 40, 50]);
// Properties
console.log('Length:', arr.length);
console.log('Byte length:', arr.byteLength);
console.log('Bytes per element:', arr.BYTES_PER_ELEMENT);
// Array methods work
const doubled = arr.map((x) => x * 2);
console.log('Doubled:', doubled);
const sum = arr.reduce((a, b) => a + b, 0);
console.log('Sum:', sum);
const filtered = arr.filter((x) => x > 25);
console.log('Filtered (>25):', filtered);
// slice() creates new TypedArray with new buffer
const sliced = arr.slice(1, 4);
console.log('Sliced:', sliced);
// subarray() creates view into same buffer
const sub = arr.subarray(1, 4);
console.log('Subarray:', sub);
// set() copies values
const target = new Uint8Array(10);
target.set([1, 2, 3], 0); // At offset 0
target.set([7, 8, 9], 5); // At offset 5
console.log('After set():', target);
// ============================================
// OVERFLOW BEHAVIOR
// ============================================
console.log('\n=== Overflow Behavior ===');
// Regular TypedArray wraps around
const uint8 = new Uint8Array([255]);
uint8[0] = 256;
console.log('Uint8Array overflow:', uint8[0]); // 0
uint8[0] = -1;
console.log('Uint8Array underflow:', uint8[0]); // 255
// Uint8ClampedArray clamps values
const clamped = new Uint8ClampedArray([255]);
clamped[0] = 256;
console.log('Clamped overflow:', clamped[0]); // 255
clamped[0] = -10;
console.log('Clamped underflow:', clamped[0]); // 0
// ============================================
// DATAVIEW
// ============================================
console.log('\n=== DataView ===');
const dvBuffer = new ArrayBuffer(16);
const view = new DataView(dvBuffer);
// Write different types at different offsets
view.setInt8(0, 127);
view.setInt16(1, 1000, true); // Little-endian
view.setInt32(3, 100000, true);
view.setFloat64(7, 3.14159);
// Read back
console.log('Int8 at 0:', view.getInt8(0));
console.log('Int16 at 1:', view.getInt16(1, true));
console.log('Int32 at 3:', view.getInt32(3, true));
console.log('Float64 at 7:', view.getFloat64(7));
// ============================================
// ENDIANNESS
// ============================================
console.log('\n=== Endianness ===');
const endianBuf = new ArrayBuffer(4);
const endianView = new DataView(endianBuf);
const endianBytes = new Uint8Array(endianBuf);
// Write 0x12345678 in different endianness
endianView.setUint32(0, 0x12345678, false); // Big-endian
console.log(
'Big-endian bytes:',
Array.from(endianBytes).map((b) => b.toString(16))
);
endianView.setUint32(0, 0x12345678, true); // Little-endian
console.log(
'Little-endian bytes:',
Array.from(endianBytes).map((b) => b.toString(16))
);
// Detect system endianness
function isLittleEndian() {
const buf = new ArrayBuffer(2);
new DataView(buf).setInt16(0, 256, true);
return new Int16Array(buf)[0] === 256;
}
console.log('System is little-endian:', isLittleEndian());
// ============================================
// STRING ENCODING
// ============================================
console.log('\n=== String Encoding ===');
// TextEncoder/TextDecoder for UTF-8
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const encoded = encoder.encode('Hello, World! 🌍');
console.log('Encoded:', encoded);
console.log('Byte length:', encoded.length);
const decoded = decoder.decode(encoded);
console.log('Decoded:', decoded);
// ============================================
// HEX CONVERSION
// ============================================
console.log('\n=== Hex Conversion ===');
function bytesToHex(bytes) {
return Array.from(bytes)
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
}
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return bytes;
}
const testBytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
const hex = bytesToHex(testBytes);
console.log('Bytes to hex:', hex);
const backToBytes = hexToBytes(hex);
console.log('Hex to bytes:', backToBytes);
// ============================================
// BASE64 CONVERSION
// ============================================
console.log('\n=== Base64 Conversion ===');
function bufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binary = '';
bytes.forEach((b) => (binary += String.fromCharCode(b)));
return btoa(binary);
}
function base64ToBuffer(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes.buffer;
}
const testBuffer = new Uint8Array([72, 101, 108, 108, 111]).buffer;
const base64 = bufferToBase64(testBuffer);
console.log('Buffer to Base64:', base64);
const backToBuffer = base64ToBuffer(base64);
console.log('Base64 to Buffer:', new Uint8Array(backToBuffer));
// ============================================
// PRACTICAL: BINARY PROTOCOL PARSING
// ============================================
console.log('\n=== Binary Protocol Parsing ===');
// Simulate a binary message: [type:1][length:2][data:n]
function createMessage(type, data) {
const dataBytes = encoder.encode(data);
const buffer = new ArrayBuffer(3 + dataBytes.length);
const view = new DataView(buffer);
view.setUint8(0, type);
view.setUint16(1, dataBytes.length, true);
new Uint8Array(buffer, 3).set(dataBytes);
return buffer;
}
function parseMessage(buffer) {
const view = new DataView(buffer);
const type = view.getUint8(0);
const length = view.getUint16(1, true);
const dataBytes = new Uint8Array(buffer, 3, length);
const data = decoder.decode(dataBytes);
return { type, length, data };
}
const msg = createMessage(1, 'Hello Protocol');
console.log('Created message bytes:', new Uint8Array(msg));
const parsed = parseMessage(msg);
console.log('Parsed:', parsed);
// ============================================
// PRACTICAL: FILE SIGNATURE CHECK
// ============================================
console.log('\n=== File Signatures ===');
const signatures = {
png: [0x89, 0x50, 0x4e, 0x47],
jpg: [0xff, 0xd8, 0xff],
pdf: [0x25, 0x50, 0x44, 0x46],
zip: [0x50, 0x4b, 0x03, 0x04],
};
function detectFileType(bytes) {
for (const [type, sig] of Object.entries(signatures)) {
if (sig.every((byte, i) => bytes[i] === byte)) {
return type;
}
}
return 'unknown';
}
// Simulate PNG header
const pngHeader = new Uint8Array([
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
]);
console.log('File type:', detectFileType(pngHeader));
// ============================================
// PRACTICAL: COLOR MANIPULATION
// ============================================
console.log('\n=== Color Manipulation ===');
// RGBA color as Uint8Array
function createRGBA(r, g, b, a = 255) {
return new Uint8Array([r, g, b, a]);
}
function invertColor(rgba) {
const inverted = new Uint8Array(4);
inverted[0] = 255 - rgba[0]; // R
inverted[1] = 255 - rgba[1]; // G
inverted[2] = 255 - rgba[2]; // B
inverted[3] = rgba[3]; // A (keep)
return inverted;
}
function grayscale(rgba) {
const gray = Math.round(0.299 * rgba[0] + 0.587 * rgba[1] + 0.114 * rgba[2]);
return new Uint8Array([gray, gray, gray, rgba[3]]);
}
const red = createRGBA(255, 0, 0);
console.log('Red:', red);
console.log('Inverted:', invertColor(red));
console.log('Grayscale:', grayscale(red));
console.log('\n=== Examples Complete ===');