use base64::Engine;
use std::io::{self, BufRead, Write};
fn b64_decode(field: &str) -> String {
if field.is_empty() {
return String::new();
}
let bytes = base64::engine::general_purpose::STANDARD
.decode(field.as_bytes())
.expect("valid base64 field");
String::from_utf8(bytes).expect("valid utf-8 field")
}
fn parse_list(decoded: &str) -> Vec<String> {
if decoded.is_empty() {
return Vec::new();
}
decoded.split('\n').map(|s| s.to_string()).collect()
}
fn main() {
let stdin = io::stdin();
let stdout = io::stdout();
let mut out = io::BufWriter::new(stdout.lock());
for line in stdin.lock().lines() {
let line = line.expect("read line");
if line.is_empty() {
continue;
}
let fields: Vec<&str> = line.split(' ').collect();
assert_eq!(fields.len(), 6, "expected 6 base64 fields per line");
let text = b64_decode(fields[0]);
let context = b64_decode(fields[1]);
let known_prefixes = parse_list(&b64_decode(fields[2]));
let secret_keywords = parse_list(&b64_decode(fields[3]));
let test_keywords = parse_list(&b64_decode(fields[4]));
let placeholder_keywords = parse_list(&b64_decode(fields[5]));
let features = keyhog_scanner::ml_scorer::compute_features_with_config(
&text,
&context,
&known_prefixes,
&secret_keywords,
&test_keywords,
&placeholder_keywords,
);
let rendered: Vec<String> = features.iter().map(|v| format!("{v:.9}")).collect();
writeln!(out, "{}", rendered.join(" ")).expect("write line");
}
out.flush().expect("flush");
}