Files
improvise/crates/zset/tests/support/mod.rs
T
2026-10-10 21:33:21 -07:00

84 lines
2.7 KiB
Rust

//! A text wire form of `u8`-keyed frames, shared by the edge tests.
use zset::{CodecError, Correction, Delta, EdgeCodec, Frame, Request, Stamp, ZSet};
type Z = ZSet<u8>;
/// A text wire form, to run the same histories through an encoding.
#[derive(Clone, Copy)]
pub struct Text;
pub fn zs(z: &Z) -> String {
z.iter()
.map(|(k, w)| format!("{k}:{w}"))
.collect::<Vec<_>>()
.join(",")
}
pub fn unzs(s: &str) -> Result<Z, CodecError> {
let bad = || CodecError(format!("bad entries {s:?}"));
s.split(',')
.filter(|p| !p.is_empty())
.map(|p| {
let (k, w) = p.split_once(':').ok_or_else(bad)?;
Ok((
k.parse::<u8>().map_err(|_| bad())?,
w.parse::<i64>().map_err(|_| bad())?,
))
})
.collect()
}
impl EdgeCodec<u8> for Text {
type Wire = String;
fn encode(&self, f: &Frame<u8>) -> String {
match f {
Frame::Delta(d) => format!("D {} {} {} {}", d.epoch, d.from, d.to, zs(&d.delta)),
Frame::Correction(c) => {
format!("C {} {} {} {}", c.epoch, c.through, c.token, zs(&c.target))
}
Frame::Request(r) => match r.have {
Some(s) => format!("R {} {} {}", r.token, s.epoch, s.seq),
None => format!("R {}", r.token),
},
}
}
fn decode(&self, w: String) -> Result<Frame<u8>, CodecError> {
let bad = || CodecError(format!("bad frame {w:?}"));
let mut it = w.splitn(5, ' ');
let num = |s: Option<&str>| s.and_then(|s| s.parse::<u64>().ok()).ok_or_else(bad);
match it.next() {
Some("D") => Ok(Frame::Delta(Delta {
epoch: num(it.next())?,
from: num(it.next())?,
to: num(it.next())?,
delta: unzs(it.next().ok_or_else(bad)?)?,
})),
Some("C") => {
let mut it = w.splitn(5, ' ');
it.next();
Ok(Frame::Correction(Correction {
epoch: num(it.next())?,
through: num(it.next())?,
token: num(it.next())?,
target: unzs(it.next().ok_or_else(bad)?)?,
}))
}
Some("R") => {
let token = num(it.next())?;
let have = match it.next() {
None => None,
e => Some(Stamp {
epoch: num(e)?,
seq: num(it.next())?,
}),
};
Ok(Frame::Request(Request { have, token }))
}
_ => Err(bad()),
}
}
}