/*
 * protocol/protocol.h — control-plane (de)serialization + routing.
 *
 * Design: docs/protocol.md. Wire format is a length-prefixed protobuf `Envelope`
 * (core/proto/voicecat.proto). This layer parses frames into Envelopes, correlates
 * request_id ↔ response, and dispatches to handlers. Media frames do NOT come through here
 * (they use the fixed binary header in voice.md §2).
 *
 * STATUS: real. Protobuf codegen is on (core/CMakeLists.txt) for VOICECAT_HAS_NET builds
 * (`dev`/`release`/`server-release`); FrameCodec below is fully implemented and used by both the
 * client (net/transport.h) and the server (conn_session.cpp). See protocol/envelope.h for the
 * Envelope-level encode/decode that sits on top of this.
 */
#ifndef VOICECAT_PROTOCOL_PROTOCOL_H
#define VOICECAT_PROTOCOL_PROTOCOL_H

#include <cstddef>
#include <cstdint>
#include <vector>

namespace voicecat::protocol {

constexpr uint32_t kProtocolVersion  = 1;
constexpr uint32_t kMaxFrameBytes    = 16u * 1024 * 1024;  // docs/protocol.md §1 guard
constexpr size_t   kLengthHeaderSize = 4;                   // big-endian u32 prefix

// Reads/writes [u32 big-endian length][payload] frames from a byte stream.
class FrameCodec {
   public:
    // Append received bytes; pop complete frame payloads into out_frames.
    // Returns false on protocol error (oversized frame or framing violation).
    bool feed(const uint8_t* data, size_t len, std::vector<std::vector<uint8_t>>& out_frames);

    // Serialize a frame into out: [big-endian u32 length][payload bytes].
    static void emit(const uint8_t* payload, size_t len, std::vector<uint8_t>& out);
    static void emit(const std::vector<uint8_t>& payload, std::vector<uint8_t>& out);

    // Number of bytes buffered but not yet forming a complete frame.
    size_t pending_bytes() const { return buf_.size(); }

    void reset() { buf_.clear(); }

   private:
    std::vector<uint8_t> buf_;
};

}  // namespace voicecat::protocol

#endif  // VOICECAT_PROTOCOL_PROTOCOL_H
