#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct CostBreakdown {
pub header: u64,
pub universe: u64,
pub format: u64,
pub record_framing: u64,
pub objects: u64,
pub graph: u64,
pub models: u64,
pub entropy_payload: u64,
pub residuals: u64,
pub index: u64,
pub integrity: u64,
pub trailer: u64,
}
impl CostBreakdown {
pub fn total(&self) -> u64 {
self.header
+ self.universe
+ self.format
+ self.record_framing
+ self.objects
+ self.graph
+ self.models
+ self.entropy_payload
+ self.residuals
+ self.index
+ self.integrity
+ self.trailer
}
pub fn to_json(&self) -> String {
let mut s = String::new();
s.push('{');
let fields: [(&str, u64); 12] = [
("header", self.header),
("universe", self.universe),
("format", self.format),
("record_framing", self.record_framing),
("objects", self.objects),
("graph", self.graph),
("models", self.models),
("entropy_payload", self.entropy_payload),
("residuals", self.residuals),
("index", self.index),
("integrity", self.integrity),
("trailer", self.trailer),
];
for (i, (name, value)) in fields.iter().enumerate() {
if i > 0 {
s.push(',');
}
s.push('"');
s.push_str(name);
s.push_str("\":");
s.push_str(&value.to_string());
}
s.push('}');
s
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn total_sums_all_fields() {
let c = CostBreakdown {
header: 64,
objects: 100,
record_framing: 24,
..Default::default()
};
assert_eq!(c.total(), 188);
}
#[test]
fn json_has_all_fields() {
let j = CostBreakdown::default().to_json();
for k in [
"header",
"universe",
"format",
"record_framing",
"objects",
"graph",
"models",
"entropy_payload",
"residuals",
"index",
"integrity",
"trailer",
] {
assert!(j.contains(k), "missing {k}");
}
}
}