use super::pipeline::{decode_candidates, extract_encoded_values};
use super::Decoder;
use keyhog_core::Chunk;
pub struct ReverseDecoder;
const MIN_REVERSE_LEN: usize = 16;
impl Decoder for ReverseDecoder {
fn name(&self) -> &'static str {
"reverse"
}
fn decode_chunk(&self, chunk: &Chunk) -> Vec<Chunk> {
if chunk.metadata.source_type.contains("/reverse") {
return Vec::new();
}
let candidates: Vec<String> = extract_encoded_values(&chunk.data)
.into_iter()
.filter(|c| c.len() >= MIN_REVERSE_LEN)
.filter(|c| looks_reversible(c))
.collect();
decode_candidates(chunk, candidates, |s| Ok(reverse_str(s)), self.name())
}
}
pub fn reverse_str(s: &str) -> String {
s.chars().rev().collect()
}
pub fn looks_reversible(candidate: &str) -> bool {
let bytes = candidate.as_bytes();
let mut run = 0usize;
let mut saw_long_run = false;
for &b in bytes.iter().rev() {
if b.is_ascii_alphanumeric() {
run += 1;
if run >= 12 {
saw_long_run = true;
break;
}
} else {
run = 0;
}
}
if !saw_long_run {
return false;
}
let reversed = reverse_str(candidate);
crate::confidence::KNOWN_PREFIXES
.iter()
.filter(|prefix| prefix.len() >= 3)
.any(|prefix| reversed.contains(prefix))
}