vole_document/encode/
court.rs1use crate::accounting::CostBreakdown;
9use crate::container::Descriptor;
10use crate::encode::candidates::{Candidate, CandidateKind};
11use crate::error::{Error, Result};
12use crate::limits::Limits;
13use crate::materialize::materialize;
14
15#[derive(Debug, Clone)]
17pub struct CourtResult {
18 pub kind: CandidateKind,
20 pub bytes: Vec<u8>,
22 pub cost: CostBreakdown,
24 pub candidates_evaluated: u32,
26 pub graph_ops: usize,
28}
29
30pub fn run(input: &[u8], candidates: Vec<Candidate>, limits: Limits) -> Result<CourtResult> {
35 let mut best: Option<(u64, usize, CandidateKind, Vec<u8>, CostBreakdown)> = None;
36 let mut evaluated: u32 = 0;
37
38 for c in candidates {
39 evaluated += 1;
40 let (bytes, cost) = c.descriptor.serialize()?;
41
42 let parsed = Descriptor::parse(&bytes, limits)?;
44 let out = materialize(&parsed, limits)?;
45 if out != input {
46 return Err(Error::reconstruction_mismatch(format!(
47 "candidate {} did not reproduce the source exactly",
48 c.kind.name()
49 )));
50 }
51
52 let total = cost.total();
53 debug_assert_eq!(total, bytes.len() as u64);
54 let work = c.descriptor.program.ops.len();
55 let key = (total, work, c.kind);
56 let replace = match &best {
57 None => true,
58 Some((bt, bw, bk, ..)) => key < (*bt, *bw, *bk),
59 };
60 if replace {
61 best = Some((total, work, c.kind, bytes, cost));
62 }
63 }
64
65 let (_, work, kind, bytes, cost) =
66 best.ok_or_else(|| Error::internal_invariant("no candidates were evaluated"))?;
67 Ok(CourtResult {
68 kind,
69 bytes,
70 cost,
71 candidates_evaluated: evaluated,
72 graph_ops: work,
73 })
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::encode::candidates;
80
81 #[test]
82 fn raw_candidate_wins_and_is_exact() {
83 let input = b"some bytes that must round trip".to_vec();
84 let cands = candidates::propose(&input, Limits::DEFAULT).unwrap();
85 let expected = cands.len() as u32;
86 let r = run(&input, cands, Limits::DEFAULT).unwrap();
87 assert_eq!(r.kind, CandidateKind::Raw);
88 assert_eq!(r.candidates_evaluated, expected);
92 assert!(r.candidates_evaluated >= 2);
93 assert_eq!(r.cost.total(), r.bytes.len() as u64);
94 let (out, _) = crate::materialize::decode_to_bytes(&r.bytes, Limits::DEFAULT).unwrap();
95 assert_eq!(out, input);
96 }
97
98 #[test]
99 fn empty_input_is_exact() {
100 let input: Vec<u8> = Vec::new();
101 let cands = candidates::propose(&input, Limits::DEFAULT).unwrap();
102 let r = run(&input, cands, Limits::DEFAULT).unwrap();
103 let (out, _) = crate::materialize::decode_to_bytes(&r.bytes, Limits::DEFAULT).unwrap();
104 assert!(out.is_empty());
105 }
106}