pub mod traits;

use rkyv::{bytecheck::CheckBytes, with::Skip};
use serde::{Deserialize, Serialize};

pub type RingSlot<T> = crossbeam_utils::CachePadded<Envelope<T>>;

#[derive(Debug, Clone)]
pub struct ResponseCallback {
    pub tx: flume::Sender<
        Result<crate::book::protocol::response::Response, crate::engine::error::EngineError>,
    >,
}

#[derive(
    Debug,
    Default,
    Clone,
    Serialize,
    Deserialize,
    rkyv::Archive,
    rkyv::Serialize,
    rkyv::Deserialize,
    CheckBytes,
)]
pub struct Envelope<T> {
    // Global Application sequence, set by publisher.
    pub seq: u64,
    pub payload: T,

    // framing
    pub tx_id: u64,  // monotonic transaction id
    pub tx_len: u16, // number of events in this transaction (solo event: 1)
    pub tx_ix: u16,  // 0-based index within the transaction (solo event: 0)

    #[serde(skip)]
    /// Runtime-only response callback for this tx (not persisted).
    #[rkyv(with = Skip)]
    pub response_cb: Option<ResponseCallback>,
}

impl<T> Envelope<T> {
    pub fn is_tx_start(&self) -> bool {
        self.tx_ix == 0
    }

    pub fn is_tx_end(&self) -> bool {
        self.tx_ix + 1 == self.tx_len
    }
}
