//! Canonical ABI for synthetic and real LOB data.
//! Phase 2A defines this; Phase 1.2 cost kernel and main eval consume it.
//! Per spec §4.4.

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct LobBar {
    pub price: f32,    // mid-price, MES futures dollar units
    pub spread: f32,   // bid-ask spread, same units as price (e.g., 0.25 = quarter-tick)
    pub ofi: f32,      // signed OFI normalized to ~[-3, 3]
}

impl LobBar {
    pub const fn new(price: f32, spread: f32, ofi: f32) -> Self {
        Self { price, spread, ofi }
    }
}

/// Convert AoS Vec<LobBar> → SoA (prices, spreads, ofis).
/// Cost-net kernel and synthetic markets both flatten on the GPU side;
/// this helper centralises the conversion.
pub fn into_soa(bars: &[LobBar]) -> (Vec<f32>, Vec<f32>, Vec<f32>) {
    let n = bars.len();
    let mut prices = Vec::with_capacity(n);
    let mut spreads = Vec::with_capacity(n);
    let mut ofis = Vec::with_capacity(n);
    for b in bars {
        prices.push(b.price);
        spreads.push(b.spread);
        ofis.push(b.ofi);
    }
    (prices, spreads, ofis)
}
