pub mod alias;
pub mod liveness;
pub mod scan;
pub use alias::resolve_alias;
pub use liveness::sid_live;
use std::path::Path;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionRow {
pub sid: String,
pub mtime: i64,
pub human_ts: String,
pub mode: String,
pub label: String,
}
impl SessionRow {
pub fn to_tsv(&self) -> String {
format!(
"{}\t{}\t{}\t{}\t{}",
self.sid, self.mtime, self.human_ts, self.mode, self.label
)
}
#[allow(dead_code)]
pub fn from_tsv(line: &str) -> Option<Self> {
let mut cols = line.splitn(5, '\t');
let sid = cols.next()?.to_owned();
let mtime: i64 = cols.next()?.parse().ok()?;
let human_ts = cols.next()?.to_owned();
let mode = cols.next()?.to_owned();
let label = cols.next()?.to_owned();
Some(SessionRow {
sid,
mtime,
human_ts,
mode,
label,
})
}
}
pub fn scan(cwd: &Path) -> Vec<SessionRow> {
scan::scan_sessions(cwd)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn session_row_tsv_roundtrip() {
let row = SessionRow {
sid: "01234567-89ab-cdef-0123-456789abcdef".to_owned(),
mtime: 1_718_000_000,
human_ts: "06-10 14:32".to_owned(),
mode: "default".to_owned(),
label: "Some conversation label".to_owned(),
};
let tsv = row.to_tsv();
let parsed = SessionRow::from_tsv(&tsv).expect("round-trip should succeed");
assert_eq!(row, parsed);
}
#[test]
fn session_row_tsv_roundtrip_empty_mode() {
let row = SessionRow {
sid: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee".to_owned(),
mtime: 0,
human_ts: "01-01 00:00".to_owned(),
mode: String::new(),
label: "label with\ttab in it? no — label is last col so tab OK".to_owned(),
};
let tsv = row.to_tsv();
let parsed = SessionRow::from_tsv(&tsv).expect("round-trip should succeed");
assert_eq!(row, parsed);
}
#[test]
fn session_row_from_tsv_rejects_short_line() {
assert!(SessionRow::from_tsv("only-three\t1234\thuman").is_none());
}
#[test]
fn session_row_from_tsv_rejects_bad_mtime() {
assert!(SessionRow::from_tsv("sid\tnot-a-number\thuman\tmode\tlabel").is_none());
}
}