use crate::embedding::EMBEDDING_DIMS;
pub fn placeholder_embedding(content: &str) -> Vec<f32> {
let mut seed: u64 = 0x1234_5678_9abc_def0;
for byte in content.bytes() {
seed = seed.wrapping_mul(31).wrapping_add(byte as u64);
}
let mut vec = Vec::with_capacity(EMBEDDING_DIMS);
for i in 0..EMBEDDING_DIMS {
let mut dim_hash = seed.wrapping_add(i as u64);
dim_hash ^= dim_hash >> 33;
dim_hash = dim_hash.wrapping_mul(0xff51_afd7_ed55_8ccd);
dim_hash ^= dim_hash >> 33;
dim_hash = dim_hash.wrapping_mul(0xc4ce_b9fe_1a85_ec53);
let value = ((dim_hash % 2000) as f32 - 1000.0) / 1000.0;
vec.push(value);
}
vec
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sqlite::embedding::{EmbeddingClass, classify_embedding};
#[test]
fn placeholder_classifies_as_mock() {
let v = placeholder_embedding("hello world");
assert_eq!(v.len(), EMBEDDING_DIMS);
assert_eq!(
classify_embedding(&v),
EmbeddingClass::Mock,
"placeholder must classify as Mock (L2 norm strictly > 2.0) so reindex backfills it"
);
}
#[test]
fn placeholder_is_deterministic_per_content() {
let a = placeholder_embedding("same input");
let b = placeholder_embedding("same input");
assert_eq!(a, b, "same content must produce the same placeholder");
}
#[test]
fn placeholder_differs_for_different_content() {
let a = placeholder_embedding("foo");
let b = placeholder_embedding("bar");
assert_ne!(
a, b,
"different content should produce different placeholders"
);
}
}