MWSE/sdk/codec.js

76 lines
3.0 KiB
JavaScript

// WSTS codec — encoder/decoder for the WebSocket frames MWSE exchanges.
//
// Infrastructure for issue #42 (binary framing). The codec is pluggable: today
// it speaks JSON text frames (mode=CODEC_JSON); the binary path (mode=CODEC_BINARY)
// is stubbed and will be wired once the server side lands.
//
// Frame shapes (codec-agnostic, defined by WSTS protocol):
// Inbound from server: [payload, signalName] — signal
// [payload, id, 'E'|'C'] — reply
// Outbound to server: [msg, 'R'] — fire-and-forget (WOM)
// [msg, id, 'R'] — request (reply once)
// [msg, id, 'S'] — stream (reply multiple)
import { CODEC_JSON, CODEC_BINARY } from './version.js';
export class WSTSCodec {
constructor() {
this.mode = CODEC_JSON;
}
// encode turns a JS frame array into a wire value (string or ArrayBuffer).
encode(frame) {
if (this.mode === CODEC_JSON) {
return JSON.stringify(frame);
}
if (this.mode === CODEC_BINARY) {
return this._encodeBinary(frame);
}
throw new Error(`WSTSCodec: unknown mode ${this.mode}`);
}
// decode turns raw wire data into a JS frame array.
decode(raw) {
if (typeof raw === 'string') {
return JSON.parse(raw);
}
if (raw instanceof ArrayBuffer) {
if (this.mode === CODEC_BINARY) {
return this._decodeBinary(raw);
}
throw new Error('WSTSCodec: received binary frame but codec is in JSON mode');
}
throw new Error(`WSTSCodec: unexpected frame type ${typeof raw}`);
}
// negotiate picks the best codec from the server's offered list and activates it.
// Returns true when a common codec was found.
negotiate(serverCodecs) {
// Prefer binary when both sides support it (future upgrade path).
if (serverCodecs.includes(CODEC_BINARY)) {
this.mode = CODEC_BINARY;
return true;
}
if (serverCodecs.includes(CODEC_JSON)) {
this.mode = CODEC_JSON;
return true;
}
return false;
}
// ---- Binary codec (issue #42) ----------------------------------------
// Wire layout: 1-byte opcode | 4-byte uint32 big-endian payload length | payload bytes
// Opcodes: 0x01 = signal, 0x02 = reply-end ('E'), 0x03 = reply-continue ('C'),
// 0x04 = request ('R'), 0x05 = stream ('S'), 0x06 = wom ('R' no id)
// Payload: MessagePack (or CBOR) encoded frame contents.
// This is intentionally NOT implemented yet — throws so callers know when they
// accidentally reach binary paths before #42 is merged.
_encodeBinary(_frame) {
throw new Error('WSTSCodec binary encoding not yet implemented (#42)');
}
_decodeBinary(_buf) {
throw new Error('WSTSCodec binary decoding not yet implemented (#42)');
}
}