use sha2::{Digest, Sha256};
pub const PRIOR_SET_SIZE: usize = 5;
pub const BASELINE_BLOOMS: usize = 10;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Bucket {
Unhinted,
Revealed,
}
impl Bucket {
pub fn as_str(self) -> &'static str {
match self {
Bucket::Unhinted => "unhinted",
Bucket::Revealed => "revealed",
}
}
pub fn parse(s: &str) -> Option<Self> {
match s {
"unhinted" => Some(Bucket::Unhinted),
"revealed" => Some(Bucket::Revealed),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MatchKind {
Exact,
Close,
None,
}
impl MatchKind {
pub fn as_str(self) -> &'static str {
match self {
MatchKind::Exact => "exact",
MatchKind::Close => "close",
MatchKind::None => "none",
}
}
}
#[derive(Debug, Clone)]
pub struct WakeGuessRow {
pub agent: String,
pub wake: Option<i64>,
pub session_id: String,
pub bloom_id: String,
pub chunk_index: u16,
pub chunk_total: u16,
pub position: u32,
pub bloom_position: usize,
pub bloom_total: usize,
pub title_shown: String,
pub guess: String,
pub model_id: Option<String>,
pub phrase_source: String,
pub phrases: Vec<String>,
pub match_kind: String,
pub match_index: Option<usize>,
pub bucket: String,
pub content_hash: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct WakeHistory {
pub sessions_at_wake: Vec<String>,
pub highest_wake: Option<i64>,
}
pub fn content_hash(text: &str) -> String {
let digest = Sha256::digest(text.as_bytes());
let mut out = String::with_capacity(digest.len() * 2);
for byte in digest {
use std::fmt::Write as _;
let _ = write!(out, "{:02x}", byte);
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn content_hash_is_lowercase_hex_of_expected_width() {
let h = content_hash("chunk text");
assert_eq!(h.len(), 64);
assert!(
h.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_uppercase())
);
}
#[test]
fn content_hash_matches_known_sha256_vector() {
assert_eq!(
content_hash(""),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
#[test]
fn content_hash_differs_for_different_text() {
assert_ne!(content_hash("alpha"), content_hash("beta"));
}
}