#!/usr/bin/env node /** * Mock "Rust binary" for testing the RustBridge IPC protocol. * Reads JSON lines from stdin via Buffer-based scanner, writes JSON lines to stdout. * Emits a ready event on startup. */ // Emit ready event const readyEvent = JSON.stringify({ event: 'ready', data: { version: '1.0.0' } }); process.stdout.write(readyEvent + '\n'); // Buffer-based newline scanner for stdin (mirrors the RustBridge approach) let stdinBuffer = Buffer.alloc(0); process.stdin.on('data', (chunk) => { stdinBuffer = Buffer.concat([stdinBuffer, chunk]); let newlineIndex; while ((newlineIndex = stdinBuffer.indexOf(0x0A)) !== -1) { const lineBuffer = stdinBuffer.subarray(0, newlineIndex); stdinBuffer = stdinBuffer.subarray(newlineIndex + 1); const line = lineBuffer.toString('utf8').trim(); if (line) { handleLine(line); } } }); /** * Backpressure-aware write to stdout. */ function writeResponse(data) { const json = JSON.stringify(data) + '\n'; if (!process.stdout.write(json)) { // Wait for drain before continuing process.stdout.once('drain', () => {}); } } function handleLine(line) { let request; try { request = JSON.parse(line); } catch { return; } const { id, method, params } = request; if (method === 'echo') { // Echo back the params as result writeResponse({ id, success: true, result: params }); } else if (method === 'largeEcho') { // Echo back params (same as echo, named distinctly for large payload tests) writeResponse({ id, success: true, result: params }); } else if (method === 'error') { // Return an error writeResponse({ id, success: false, error: 'Test error message' }); } else if (method === 'emitEvent') { // Emit a custom event, then respond with success writeResponse({ event: params.eventName, data: params.eventData }); writeResponse({ id, success: true, result: null }); } else if (method === 'slow') { // Respond after a delay setTimeout(() => { writeResponse({ id, success: true, result: { delayed: true } }); }, 100); } else if (method === 'streamEcho') { // Send params.count stream chunks, then final response const count = params.count || 0; let sent = 0; const interval = setInterval(() => { if (sent < count) { writeResponse({ id, stream: true, data: { index: sent, value: `chunk_${sent}` } }); sent++; } else { clearInterval(interval); writeResponse({ id, success: true, result: { totalChunks: count } }); } }, 10); } else if (method === 'streamError') { // Send 1 chunk, then error writeResponse({ id, stream: true, data: { index: 0, value: 'before_error' } }); setTimeout(() => { writeResponse({ id, success: false, error: 'Stream error after chunk' }); }, 20); } else if (method === 'streamEmpty') { // Zero chunks, immediate final response writeResponse({ id, success: true, result: { totalChunks: 0 } }); } else if (method === 'exit') { // Graceful exit writeResponse({ id, success: true, result: null }); process.exit(0); } else { // Unknown command writeResponse({ id, success: false, error: `Unknown method: ${method}` }); } } // Handle SIGTERM gracefully process.on('SIGTERM', () => { process.exit(0); });