use ratatui::layout::Rect;
use crate::widget::RenderCtx;
pub trait Renderable {
fn content_hash(&self) -> u64;
fn height_for(&self, width: u16, ctx: &RenderCtx) -> u16;
fn render(&mut self, area: Rect, ctx: &mut RenderCtx);
}
#[must_use]
pub fn hash_combine(a: u64, b: u64) -> u64 {
const FNV_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
const FNV_PRIME: u64 = 0x0000_0100_0000_01b3;
let mut h = a ^ b;
h = h.wrapping_mul(FNV_PRIME) ^ (h >> 31);
h ^ FNV_OFFSET
}
#[must_use]
pub fn hash_str(s: &str) -> u64 {
use std::hash::{Hash, Hasher};
let mut hasher = std::collections::hash_map::DefaultHasher::new();
s.hash(&mut hasher);
hasher.finish()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hash_combine_is_deterministic() {
let h1 = hash_combine(12345, 67890);
let h2 = hash_combine(12345, 67890);
assert_eq!(h1, h2);
}
#[test]
fn hash_combine_differs_on_different_inputs() {
let h1 = hash_combine(12345, 67890);
let h2 = hash_combine(12345, 67891);
assert_ne!(h1, h2);
}
#[test]
fn hash_str_is_deterministic() {
assert_eq!(hash_str("hello"), hash_str("hello"));
assert_ne!(hash_str("hello"), hash_str("world"));
}
}