use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use crate::session_id::SessionId;
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub(crate) struct ProcessIdentity {
pub pid: u32,
pub creation_time: u64,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub(crate) struct SessionRecord {
pub id: u32,
pub supervisor_pid: u32,
pub supervisor_creation_time: u64,
pub pipe_name: String,
pub launch_directory: PathBuf,
pub command: Vec<String>,
pub started_at_unix_ms: u64,
#[serde(default)]
pub attached: bool,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub(crate) enum StoredSession {
Reserved {
owner: ProcessIdentity,
},
Published(SessionRecord),
}
impl ProcessIdentity {
#[cfg(test)]
pub(crate) fn for_test(pid: u32) -> Self {
Self {
pid,
creation_time: 0,
}
}
}
impl SessionRecord {
#[must_use]
pub(crate) fn session_id(&self) -> SessionId {
SessionId::from_u32(self.id).expect(
"records are published from allocate_id and rejected on read unless the id is positive",
)
}
#[must_use]
pub(crate) fn identity(&self) -> ProcessIdentity {
ProcessIdentity {
pid: self.supervisor_pid,
creation_time: self.supervisor_creation_time,
}
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
fn sample() -> SessionRecord {
SessionRecord {
id: 1,
supervisor_pid: 42,
supervisor_creation_time: 99,
pipe_name: r"\\.\pipe\dure-abc".to_string(),
launch_directory: PathBuf::from(r"C:\work"),
command: vec!["copilot.exe".to_string()],
started_at_unix_ms: 1,
attached: false,
}
}
#[test]
fn round_trips_json() {
let record = sample();
let json = serde_json::to_string(&record).unwrap();
let parsed: SessionRecord = serde_json::from_str(&json).unwrap();
assert_eq!(parsed, record);
}
#[test]
fn identity_uses_pid_and_creation_time() {
let identity = sample().identity();
assert_eq!(identity.pid, 42);
assert_eq!(identity.creation_time, 99);
}
#[test]
fn a_reservation_and_a_published_record_are_distinguishable_on_disk() {
let owner = ProcessIdentity {
pid: 7,
creation_time: 8,
};
let reserved = StoredSession::Reserved { owner };
let published = StoredSession::Published(sample());
let reserved_json = serde_json::to_string(&reserved).unwrap();
let published_json = serde_json::to_string(&published).unwrap();
assert_ne!(reserved_json, published_json);
assert_eq!(
serde_json::from_str::<StoredSession>(&reserved_json).unwrap(),
reserved
);
assert_eq!(
serde_json::from_str::<StoredSession>(&published_json).unwrap(),
published
);
}
}