import c from 'compact-encoding' /** Wire schema for payload records inside message `event` (uint8 in frame). */ export const BARE_OS_CHAT_WIRE_SCHEMA_VERSION = 1 /** Event kinds for `evtKind`. */ export const BARE_OS_CHAT_EVT_TEXT = 1 export const BARE_OS_CHAT_EVT_PRESENCE = 2 /** * @param {number} len */ function fixedBuffer(len) { return { preencode(state, m) { void m state.end += len }, encode(state, m) { const b = m instanceof Uint8Array ? m : /** @type {Uint8Array} */ (new Uint8Array(m)) if (b.byteLength !== len) { throw new Error(`fixed buffer: expected ${len} bytes`) } state.buffer.set(b, state.start) state.start += len }, decode(state) { const out = state.buffer.subarray(state.start, state.start + len) state.start += len return out } } } const buf16 = fixedBuffer(16) const buf32 = fixedBuffer(32) /** Message 0: hello — version + chat capability flag. */ export const msgChatHelloEncoding = { preencode(state, m) { c.uint16.preencode(state, m.chatSchemaVersion) c.bool.preencode(state, m.swarmChatCapability) }, encode(state, m) { c.uint16.encode(state, m.chatSchemaVersion) c.bool.encode(state, !!m.swarmChatCapability) }, decode(state) { return { chatSchemaVersion: c.uint16.decode(state), swarmChatCapability: c.bool.decode(state) } } } /** Message 1: helloAck — negotiated limits. */ export const msgChatHelloAckEncoding = { preencode(state, m) { c.uint16.preencode(state, m.chatSchemaVersion) c.uint32.preencode(state, m.maxPayloadBytes) }, encode(state, m) { c.uint16.encode(state, m.chatSchemaVersion) c.uint32.encode(state, m.maxPayloadBytes >>> 0) }, decode(state) { return { chatSchemaVersion: c.uint16.decode(state), maxPayloadBytes: c.uint32.decode(state) } } } /** Message 2: join room. */ export const msgChatJoinEncoding = { preencode(state, m) { c.string.preencode(state, m.roomId) c.string.preencode(state, m.displayName) buf32.preencode(state, m.senderPk) buf16.preencode(state, m.clientInstanceId) }, encode(state, m) { c.string.encode(state, m.roomId) c.string.encode(state, m.displayName) buf32.encode(state, m.senderPk) buf16.encode(state, m.clientInstanceId) }, decode(state) { return { roomId: c.string.decode(state), displayName: c.string.decode(state), senderPk: buf32.decode(state), clientInstanceId: buf16.decode(state) } } } /** Message 3: leave room. */ export const msgChatLeaveEncoding = { preencode(state, m) { c.string.preencode(state, m.roomId) }, encode(state, m) { c.string.encode(state, m.roomId) }, decode(state) { return { roomId: c.string.decode(state) } } } /** Optional detached signature (Ed25519, length-prefixed buffer). */ const optionalSigEncoding = { preencode(state, m) { const has = !!(m.sigDetached && m.sigDetached.byteLength > 0) c.bool.preencode(state, has) if (has) c.buffer.preencode(state, m.sigDetached) }, encode(state, m) { const has = !!(m.sigDetached && m.sigDetached.byteLength > 0) c.bool.encode(state, has) if (has) c.buffer.encode(state, m.sigDetached) }, decode(state) { const has = c.bool.decode(state) return has ? c.buffer.decode(state) : null } } /** Message 4: chat event (text, presence, gossip relay). */ export const msgChatEventEncoding = { preencode(state, m) { c.uint8.preencode(state, m.schemaVersion) c.uint8.preencode(state, m.evtKind) c.string.preencode(state, m.roomId) buf16.preencode(state, m.evtId) c.uint.preencode(state, m.tsMs) buf32.preencode(state, m.senderPk) c.string.preencode(state, m.displayName) c.string.preencode(state, m.body) c.uint8.preencode(state, m.ttl) optionalSigEncoding.preencode(state, m) }, encode(state, m) { c.uint8.encode(state, m.schemaVersion) c.uint8.encode(state, m.evtKind) c.string.encode(state, m.roomId) buf16.encode(state, m.evtId) c.uint.encode(state, m.tsMs) buf32.encode(state, m.senderPk) c.string.encode(state, m.displayName) c.string.encode(state, m.body) c.uint8.encode(state, m.ttl) optionalSigEncoding.encode(state, m) }, decode(state) { const schemaVersion = c.uint8.decode(state) const evtKind = c.uint8.decode(state) const roomId = c.string.decode(state) const evtId = buf16.decode(state) const tsMs = c.uint.decode(state) const senderPk = buf32.decode(state) const displayName = c.string.decode(state) const body = c.string.decode(state) const ttl = c.uint8.decode(state) const sigDetached = optionalSigEncoding.decode(state) return { schemaVersion, evtKind, roomId, evtId, tsMs, senderPk, displayName, body, ttl, sigDetached } } } /** Message 5: control stub (room list later). */ export const msgChatControlEncoding = { preencode(state, m) { c.string.preencode(state, m.op) c.string.preencode(state, m.payloadJson) }, encode(state, m) { c.string.encode(state, m.op) c.string.encode(state, m.payloadJson || '') }, decode(state) { return { op: c.string.decode(state), payloadJson: c.string.decode(state) } } }