use serde_json::{Map, Value};
use super::fields;
pub(crate) const KIND: &str = "work-diff";
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Diff {
pub project: String,
pub ball_id: String,
pub handle: Option<String>,
pub delivered: Option<String>,
pub state: String,
pub target: Option<String>,
pub source: Option<String>,
pub target_oid: Option<String>,
pub source_oid: Option<String>,
pub missing: Vec<String>,
pub files: Vec<Churn>,
pub truncated: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Churn {
pub path: String,
pub added: Option<u64>,
pub removed: Option<u64>,
pub binary: Option<bool>,
}
pub(crate) fn diff(value: &Value) -> Result<Diff, String> {
let obj: &Map<String, Value> = value.as_object().ok_or("attempt: not an object")?;
Ok(Diff {
project: fields::text(obj, "project")?,
ball_id: fields::text(obj, "ball_id")?,
handle: fields::opt_text(obj, "handle")?,
delivered: fields::opt_text(obj, "delivered")?,
state: fields::text(obj, "state")?,
target: fields::opt_text(obj, "target")?,
source: fields::opt_text(obj, "source")?,
target_oid: fields::opt_text(obj, "target_oid")?,
source_oid: fields::opt_text(obj, "source_oid")?,
missing: fields::strings(obj, "missing")?,
files: match obj.get("files") {
None => Vec::new(),
Some(_) => fields::list(obj, "files", churn)?,
},
truncated: fields::opt_flag(obj, "truncated")?,
})
}
fn churn(value: &Value) -> Result<Churn, String> {
let obj: &Map<String, Value> = value.as_object().ok_or("changed file: not an object")?;
Ok(Churn {
path: fields::text(obj, "path")?,
added: fields::opt_count(obj, "added")?,
removed: fields::opt_count(obj, "removed")?,
binary: fields::opt_flag(obj, "binary")?,
})
}
#[cfg(test)]
mod tests;