jay-compositor 1.13.0

The Jay compositor
use {
    crate::utils::send_sync_rc::SendSyncRc,
    bincode::{Deserializer, Options},
    jay_config::_private::bincode_ops,
    serde::{Deserialize, Serialize},
    std::time::SystemTime,
    thiserror::Error,
};

#[derive(Default)]
pub struct SmSessionIn {
    pub last_acquire: SmSessionInUseData,
}

#[derive(Default)]
pub struct SmSessionInUseData {
    pub exe: Option<SendSyncRc<String>>,
}

pub struct SmSessionOut {
    #[expect(dead_code)]
    pub first_acquire: SmSessionOutUseData,
    #[expect(dead_code)]
    pub last_acquire: SmSessionOutUseData,
}

pub struct SmSessionOutUseData {
    pub exe: Option<String>,
    pub time: SystemTime,
}

#[derive(Debug, Error)]
pub enum DeserializeSessionError {
    #[error("Could not deserialize the V0 component")]
    DeserializeV0(#[source] bincode::Error),
}

pub fn deserialize_session(data: &[u8]) -> Result<SmSessionOut, DeserializeSessionError> {
    let wire = deserialize_session_(data)?;
    Ok(wire.into())
}

fn deserialize_session_(data: &[u8]) -> Result<WireSession<'_>, DeserializeSessionError> {
    let mut des = Deserializer::from_slice(data, bincode_ops());
    macro_rules! des {
        ($err:ident) => {
            Deserialize::deserialize(&mut des).map_err(DeserializeSessionError::$err)
        };
    }
    let wire = WireSession {
        v0: des!(DeserializeV0)?,
    };
    Ok(wire)
}

pub fn serialize_session(data: &mut Vec<u8>, tl: &SmSessionIn) {
    let wire = WireSession::from(tl);
    serialize_session_(data, &wire);
}

pub fn patch_session(
    data: &mut Vec<u8>,
    old: &[u8],
    new: &SmSessionIn,
) -> Result<SmSessionOut, DeserializeSessionError> {
    let old = deserialize_session_(old)?;
    let mut wire = WireSession::from(new);
    wire.v0.first_acquire = old.v0.first_acquire;
    serialize_session_(data, &wire);
    Ok(wire.into())
}

fn serialize_session_(data: &mut Vec<u8>, wire: &WireSession<'_>) {
    data.clear();
    bincode_ops().serialize_into(data, wire).unwrap();
}

#[derive(Serialize, Deserialize)]
pub struct WireSession<'a> {
    #[serde(borrow)]
    v0: WireSessionV0<'a>,
}

#[derive(Serialize, Deserialize)]
struct WireSessionV0<'a> {
    version: u32,
    #[serde(borrow)]
    first_acquire: WireSessionUserV0<'a>,
    #[serde(borrow)]
    last_acquire: WireSessionUserV0<'a>,
}

#[derive(Copy, Clone, Serialize, Deserialize)]
struct WireSessionUserV0<'a> {
    exe: Option<&'a str>,
    time: SystemTime,
}

impl<'a> From<&'a SmSessionIn> for WireSession<'a> {
    fn from(value: &'a SmSessionIn) -> Self {
        Self { v0: value.into() }
    }
}

impl<'a> From<&'a SmSessionIn> for WireSessionV0<'a> {
    fn from(value: &'a SmSessionIn) -> Self {
        let last_acquire = WireSessionUserV0::from(&value.last_acquire);
        Self {
            version: 0,
            first_acquire: last_acquire,
            last_acquire,
        }
    }
}

impl From<WireSession<'_>> for SmSessionOut {
    fn from(value: WireSession<'_>) -> Self {
        Self {
            first_acquire: value.v0.first_acquire.into(),
            last_acquire: value.v0.last_acquire.into(),
        }
    }
}

impl<'a> From<&'a SmSessionInUseData> for WireSessionUserV0<'a> {
    fn from(value: &'a SmSessionInUseData) -> Self {
        Self {
            exe: value.exe.as_deref().map(|v| &**v),
            time: SystemTime::now(),
        }
    }
}

impl<'a> From<&'a SmSessionOutUseData> for WireSessionUserV0<'a> {
    fn from(value: &'a SmSessionOutUseData) -> Self {
        Self {
            exe: value.exe.as_deref(),
            time: value.time,
        }
    }
}

impl From<WireSessionUserV0<'_>> for SmSessionOutUseData {
    fn from(value: WireSessionUserV0<'_>) -> Self {
        Self {
            exe: value.exe.map(|v| v.to_owned()),
            time: value.time,
        }
    }
}