CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-google-protobuf

Protocol Buffers JavaScript runtime library for serializing structured data

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

bytestring-utilities.mddocs/

ByteString Utilities

ByteString is a specialized class for handling binary data (bytes fields) in Protocol Buffer messages. It provides safe, immutable handling of byte arrays with conversion utilities between different formats.

Core ByteString Class { .api }

const { ByteString } = require('google-protobuf');

// Create from base64 string
const fromB64 = ByteString.fromBase64("SGVsbG8gV29ybGQ=");

// Create from Uint8Array or array of numbers
const fromBytes = ByteString.fromUint8Array(new Uint8Array([72, 101, 108, 108, 111]));

// Create empty ByteString
const empty = ByteString.empty();

// Check if empty
const isEmpty = byteString.isEmpty();

// Get length
const length = byteString.getLength();

Type Definitions:

/**
 * @constructor
 * Immutable wrapper for bytes fields
 */

/**
 * @param {string} value Base64 encoded string (RFC 4648 section 4)
 * @return {!ByteString}
 */

/**
 * @param {!Uint8Array|!Array<number>} value Byte array data
 * @return {!ByteString}
 */

ByteString Conversion Methods { .api }

Base64 Conversion

const { ByteString } = require('google-protobuf');

// Create from base64
const bs = ByteString.fromBase64("SGVsbG8gV29ybGQ=");

// Convert to base64
const base64String = bs.toBase64();
console.log(base64String); // "SGVsbG8gV29ybGQ="

// URL-safe base64 (alternative encoding)
const urlSafeB64 = bs.toBase64(true); // Uses URL-safe alphabet

Byte Array Conversion

// Create from Uint8Array
const bytes = new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]);
const bs = ByteString.fromUint8Array(bytes);

// Convert to Uint8Array
const restored = bs.toUint8Array();
console.log(restored); // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100])

// Create from regular array of numbers
const numberArray = [65, 66, 67];
const bsFromArray = ByteString.fromUint8Array(numberArray);

String Conversion

const { ByteString } = require('google-protobuf');

// Create from UTF-8 string
const message = "Hello, 世界!";
const utf8Bytes = new TextEncoder().encode(message);
const bs = ByteString.fromUint8Array(utf8Bytes);

// Convert back to string (requires manual UTF-8 decoding)
const restoredBytes = bs.toUint8Array();
const restoredMessage = new TextDecoder().decode(restoredBytes);
console.log(restoredMessage); // "Hello, 世界!"

// Work with binary strings
const binaryData = "\x48\x65\x6C\x6C\x6F"; // "Hello" as binary string
const binaryBytes = new Uint8Array([...binaryData].map(c => c.charCodeAt(0)));
const bsFromBinary = ByteString.fromUint8Array(binaryBytes);

ByteString Comparison and Equality { .api }

const { ByteString } = require('google-protobuf');

const bs1 = ByteString.fromBase64("SGVsbG8="); // "Hello"
const bs2 = ByteString.fromUint8Array([72, 101, 108, 108, 111]); // Same data
const bs3 = ByteString.fromBase64("V29ybGQ="); // "World"

// ByteString comparison
const areEqual = bs1.equals(bs2);
console.log(areEqual); // true

const areDifferent = bs1.equals(bs3);
console.log(areDifferent); // false

// Compare with null/undefined
const nullComparison = bs1.equals(null);
console.log(nullComparison); // false

// Hash code for use in maps/sets
const hash1 = bs1.hashCode();
const hash2 = bs2.hashCode();
console.log(hash1 === hash2); // true (same data = same hash)

Type Definitions:

/**
 * @param {?ByteString} other ByteString to compare with
 * @return {boolean} Whether the ByteStrings contain identical data
 */

/**
 * @return {number} Hash code for this ByteString
 */

Integration with Protocol Buffers { .api }

Message Field Usage

const { ByteString } = require('google-protobuf');

// Example: Working with bytes fields in generated messages
class DocumentMessage extends Message {
  getContent() { return this.content_; }
  setContent(value) { this.content_ = value; }
  
  getThumbnail() { return this.thumbnail_; }
  setThumbnail(value) { this.thumbnail_ = value; }
}

// Set bytes field using ByteString
const document = new DocumentMessage();

// From file data
const fileData = new Uint8Array([/* file bytes */]);
const contentBytes = ByteString.fromUint8Array(fileData);
document.setContent(contentBytes);

// From base64 encoded thumbnail
const thumbnailB64 = "iVBORw0KGgoAAAANSUhEUgAA..."; // Base64 image data
const thumbnailBytes = ByteString.fromBase64(thumbnailB64);
document.setThumbnail(thumbnailBytes);

// Serialize message (ByteString handles conversion automatically)
const serialized = document.serializeBinary();

// Deserialize and access bytes
const restored = DocumentMessage.deserializeBinary(serialized);
const restoredContent = restored.getContent(); // Returns ByteString
const contentAsBytes = restoredContent.toUint8Array();

Binary I/O Integration

const { BinaryReader, BinaryWriter, ByteString } = require('google-protobuf');

// Writing ByteString with BinaryWriter
const writer = new BinaryWriter();
const data = ByteString.fromBase64("SGVsbG8=");

writer.writeBytes(1, data); // ByteString automatically handled
const result = writer.getResultBuffer();

// Reading ByteString with BinaryReader
const reader = new BinaryReader(result);
while (reader.nextField()) {
  if (reader.getFieldNumber() === 1) {
    const readBytes = reader.readBytes(); // Returns Uint8Array by default
    const asByteString = ByteString.fromUint8Array(readBytes);
    console.log(asByteString.toBase64()); // "SGVsbG8="
  }
}

Performance and Memory Considerations { .api }

Immutability Benefits

const { ByteString } = require('google-protobuf');

// ByteString is immutable - safe to share references
const originalData = ByteString.fromBase64("SGVsbG8=");
const sharedRef1 = originalData;
const sharedRef2 = originalData;

// No risk of accidental mutation
console.log(sharedRef1 === sharedRef2); // true - same object reference
console.log(sharedRef1.equals(sharedRef2)); // true - same data

// Operations create new instances
const base64String = originalData.toBase64(); // Safe conversion
const byteArray = originalData.toUint8Array(); // Creates new Uint8Array

Memory Optimization

// Efficient for repeated operations
const cache = new Map();

function getOrCreateByteString(base64Data) {
  if (!cache.has(base64Data)) {
    cache.set(base64Data, ByteString.fromBase64(base64Data));
  }
  return cache.get(base64Data);
}

// Reuse ByteString instances for identical data
const bs1 = getOrCreateByteString("SGVsbG8=");
const bs2 = getOrCreateByteString("SGVsbG8=");
console.log(bs1 === bs2); // true - same cached instance

Conversion Best Practices

const { ByteString } = require('google-protobuf');

// Efficient: Create once, use multiple times
const data = ByteString.fromUint8Array(largeByteArray);
const base64 = data.toBase64();
const restored = data.toUint8Array();

// Less efficient: Multiple conversions
// Don't do this in performance-critical code:
function inefficientUsage(base64Data) {
  return ByteString.fromBase64(base64Data)
    .toUint8Array()
    .map(b => b.toString(16))
    .join('');
}

// Better: Convert once, work with result
function efficientUsage(base64Data) {
  const bs = ByteString.fromBase64(base64Data);
  const bytes = bs.toUint8Array();
  return bytes.map(b => b.toString(16)).join('');
}

Error Handling { .api }

Invalid Input Handling

const { ByteString } = require('google-protobuf');

// Base64 validation
try {
  const invalid = ByteString.fromBase64("Invalid!Base64@"); // May throw
} catch (error) {
  console.error("Invalid base64:", error.message);
}

// Safe creation with validation
function createSafeByteString(base64Input) {
  try {
    return ByteString.fromBase64(base64Input);
  } catch (error) {
    console.warn("Invalid base64 input, creating empty ByteString");
    return ByteString.empty();
  }
}

// Array input validation
const validBytes = [0, 255, 128]; // Valid byte values
const invalidBytes = [256, -1, 300]; // Will be truncated to valid range

const bs1 = ByteString.fromUint8Array(validBytes);
const bs2 = ByteString.fromUint8Array(invalidBytes); // Values converted to valid bytes

Null and Undefined Handling

// Safe handling of null/undefined
function safeByteStringOps(maybeByteString) {
  if (!maybeByteString) {
    return ByteString.empty();
  }
  
  if (maybeByteString instanceof ByteString) {
    return maybeByteString;
  }
  
  // Handle string input
  if (typeof maybeByteString === 'string') {
    try {
      return ByteString.fromBase64(maybeByteString);
    } catch {
      return ByteString.empty();
    }
  }
  
  // Handle array input
  if (Array.isArray(maybeByteString) || maybeByteString instanceof Uint8Array) {
    return ByteString.fromUint8Array(maybeByteString);
  }
  
  return ByteString.empty();
}

Common Use Cases

File Upload/Download

const { ByteString } = require('google-protobuf');

// File upload: Convert File to ByteString
async function fileToByteString(file) {
  const arrayBuffer = await file.arrayBuffer();
  const uint8Array = new Uint8Array(arrayBuffer);
  return ByteString.fromUint8Array(uint8Array);
}

// File download: Convert ByteString to downloadable blob
function byteStringToBlob(byteString, mimeType = 'application/octet-stream') {
  const bytes = byteString.toUint8Array();
  return new Blob([bytes], { type: mimeType });
}

// Usage example
async function handleFileUpload(fileInput) {
  const file = fileInput.files[0];
  const byteString = await fileToByteString(file);
  
  // Store in Protocol Buffer message
  const message = new FileMessage();
  message.setContent(byteString);
  message.setFileName(file.name);
  message.setMimeType(file.type);
  
  return message;
}

Image Processing

// Working with image data
async function processImage(imageByteString) {
  // Convert to blob for canvas processing
  const blob = new Blob([imageByteString.toUint8Array()], { type: 'image/jpeg' });
  const imageUrl = URL.createObjectURL(blob);
  
  // Load into canvas
  const img = new Image();
  img.src = imageUrl;
  
  await new Promise(resolve => img.onload = resolve);
  
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = img.width;
  canvas.height = img.height;
  ctx.drawImage(img, 0, 0);
  
  // Process and return as ByteString
  const processedBlob = await new Promise(resolve => canvas.toBlob(resolve));
  const processedBytes = new Uint8Array(await processedBlob.arrayBuffer());
  
  URL.revokeObjectURL(imageUrl);
  return ByteString.fromUint8Array(processedBytes);
}

docs

binary-io.md

bytestring-utilities.md

debug-utilities.md

extension-fields.md

index.md

map-operations.md

message-operations.md

tile.json