import { AMQPView } from "./amqp-view.js" import type { Field } from "./amqp-properties.js" // AMQP Frame Types (from AMQP 0-9-1 spec) export enum Type { METHOD = 1, HEADER = 2, BODY = 3, HEARTBEAT = 8, } // AMQP Frame End Byte (from AMQP 0-9-1 spec) export enum End { CODE = 206, } // AMQP Class IDs (partial, add more as needed) export enum ClassId { CONNECTION = 10, CHANNEL = 20, EXCHANGE = 40, QUEUE = 50, BASIC = 60, TX = 90, CONFIRM = 85, } // AMQP Method IDs by class (partial, add more as needed) export enum ConnectionMethod { START = 10, START_OK = 11, SECURE = 20, SECURE_OK = 21, TUNE = 30, TUNE_OK = 31, OPEN = 40, OPEN_OK = 41, CLOSE = 50, CLOSE_OK = 51, BLOCKED = 60, UNBLOCKED = 61, UPDATE_SECRET = 70, UPDATE_SECRET_OK = 71, } export enum ChannelMethod { OPEN = 10, OPEN_OK = 11, FLOW = 20, FLOW_OK = 21, CLOSE = 40, CLOSE_OK = 41, } export enum ExchangeMethod { DECLARE = 10, DECLARE_OK = 11, DELETE = 20, DELETE_OK = 21, BIND = 30, BIND_OK = 31, UNBIND = 40, UNBIND_OK = 51, } export enum QueueMethod { DECLARE = 10, DECLARE_OK = 11, BIND = 20, BIND_OK = 21, PURGE = 30, PURGE_OK = 31, DELETE = 40, DELETE_OK = 41, UNBIND = 50, UNBIND_OK = 51, } export enum BasicMethod { QOS = 10, QOS_OK = 11, CONSUME = 20, CONSUME_OK = 21, CANCEL = 30, CANCEL_OK = 31, PUBLISH = 40, RETURN = 50, DELIVER = 60, GET = 70, GET_OK = 71, GET_EMPTY = 72, ACK = 80, REJECT = 90, RECOVER_ASYNC = 100, RECOVER = 110, RECOVER_OK = 111, NACK = 120, } export enum TxMethod { SELECT = 10, SELECT_OK = 11, COMMIT = 20, COMMIT_OK = 21, ROLLBACK = 30, ROLLBACK_OK = 31, } export enum ConfirmMethod { SELECT = 10, SELECT_OK = 11, } interface FrameOptions { bufferSize: number type: Type channel: number frameSize?: number classId: ClassId method: number } export class Writer { view: AMQPView offset: number constructor(options: FrameOptions) { this.view = new AMQPView(new ArrayBuffer(options.bufferSize)) this.offset = 0 this.writeUint8(options.type) this.writeUint16(options.channel) this.writeUint32(options.frameSize ?? 0) this.writeUint16(options.classId) this.writeUint16(options.method) } finalize() { const currentFrameSize = this.view.getUint32(3) if (currentFrameSize === 0) { const value = this.offset - 7 // Subtract the size of the header (1 + 2 + 4) this.view.setUint32(3, value) } this.view.setUint8(this.offset, End.CODE) this.offset += 1 // Update offset to point after the frame end byte } getBuffer() { return this.view.buffer } toUint8Array() { return new Uint8Array(this.view.buffer, 0, this.offset) } writeUint8(value: number) { this.view.setUint8(this.offset, value) this.offset += 1 } writeUint16(value: number) { this.view.setUint16(this.offset, value) this.offset += 2 } writeUint32(value: number) { this.view.setUint32(this.offset, value) this.offset += 4 } writeUint64(value: number) { this.view.setUint64(this.offset, value) this.offset += 8 } writeShortString(value: string) { // Assumes setShortString returns the number of bytes written const bytesWritten = this.view.setShortString(this.offset, value) this.offset += bytesWritten } writeLongString(value: string) { // Assumes setLongString returns the number of bytes written const bytesWritten = this.view.setLongString(this.offset, value) this.offset += bytesWritten } writeTable(table: Record) { // Assumes setTable returns the number of bytes written const bytesWritten = this.view.setTable(this.offset, table) this.offset += bytesWritten } }