use serde_json::{Map, Value};
use super::fields;
pub(crate) const KIND: &str = "workspaces";
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Workspaces {
pub rows: Vec<WsRow>,
pub stale: Option<String>,
pub growth: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WsRow {
pub workspace: String,
pub kind: WorkspaceKind,
pub attention: u64,
pub agents: u64,
pub running: bool,
pub pinned: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WorkspaceKind {
Named,
Foreign,
Replay,
Unknown(String),
}
impl WorkspaceKind {
pub fn label(&self) -> String {
match self {
Self::Named => NAMED.to_owned(),
Self::Foreign => FOREIGN.to_owned(),
Self::Replay => REPLAY.to_owned(),
Self::Unknown(word) => word.clone(),
}
}
}
const NAMED: &str = "named";
const FOREIGN: &str = "foreign";
const REPLAY: &str = "replay";
pub(crate) fn workspaces(obj: &Map<String, Value>) -> Result<Workspaces, String> {
Ok(Workspaces {
rows: fields::rows(obj, row)?,
stale: fields::opt_text(obj, "stale")?,
growth: fields::opt_text(obj, "growth")?,
})
}
fn row(v: &Value) -> Result<WsRow, String> {
let o = v.as_object().ok_or("workspace row: not an object")?;
Ok(WsRow {
workspace: fields::text(o, "workspace")?,
kind: kind(&fields::text(o, "kind")?),
attention: fields::count(o, "attention")?,
agents: fields::count(o, "agents")?,
running: fields::flag(o, "running")?,
pinned: match o.get("pinned") {
None | Some(Value::Null) => None,
Some(_) => Some(fields::count(o, "pinned")?),
},
})
}
fn kind(word: &str) -> WorkspaceKind {
match word {
NAMED => WorkspaceKind::Named,
FOREIGN => WorkspaceKind::Foreign,
REPLAY => WorkspaceKind::Replay,
other => WorkspaceKind::Unknown(other.to_owned()),
}
}
#[cfg(test)]
mod tests;