vole_document/encode/
mod.rs1pub mod candidates;
4pub mod court;
5
6use crate::accounting::CostBreakdown;
7use crate::encode::candidates::CandidateKind;
8use crate::error::Result;
9use crate::integrity::{sha256, to_hex};
10use crate::limits::Limits;
11
12#[derive(Debug, Clone)]
14pub struct EncodeReport {
15 pub kind: CandidateKind,
17 pub source_len: u64,
19 pub encoded_len: u64,
21 pub cost: CostBreakdown,
23 pub sha256_hex: String,
25 pub candidates_evaluated: u32,
27 pub graph_ops: usize,
29}
30
31impl EncodeReport {
32 pub fn compression_ratio(&self) -> f64 {
34 if self.encoded_len == 0 {
35 return 0.0;
36 }
37 self.source_len as f64 / self.encoded_len as f64
38 }
39}
40
41pub fn encode(input: &[u8], limits: Limits) -> Result<(Vec<u8>, EncodeReport)> {
46 let cands = candidates::propose(input, limits)?;
47 let result = court::run(input, cands, limits)?;
48 let report = EncodeReport {
49 kind: result.kind,
50 source_len: input.len() as u64,
51 encoded_len: result.bytes.len() as u64,
52 cost: result.cost,
53 sha256_hex: to_hex(&sha256(input)),
54 candidates_evaluated: result.candidates_evaluated,
55 graph_ops: result.graph_ops,
56 };
57 Ok((result.bytes, report))
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn encode_decode_identity() {
66 let input: Vec<u8> = (0..=255u8).cycle().take(10_000).collect();
67 let (bytes, report) = encode(&input, Limits::DEFAULT).unwrap();
68 assert_eq!(report.source_len, input.len() as u64);
69 assert_eq!(report.encoded_len, bytes.len() as u64);
70 let (out, _) = crate::materialize::decode_to_bytes(&bytes, Limits::DEFAULT).unwrap();
71 assert_eq!(out, input);
72 }
73
74 #[test]
75 fn deterministic_output() {
76 let input = b"determinism check".to_vec();
77 let (a, _) = encode(&input, Limits::DEFAULT).unwrap();
78 let (b, _) = encode(&input, Limits::DEFAULT).unwrap();
79 assert_eq!(a, b);
80 }
81}