use serde_json::Value;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Record {
pub raw: Value,
pub score: Option<f64>,
}
impl Record {
pub fn new(raw: Value) -> Self {
Self { raw, score: None }
}
pub fn from_items(items: Vec<Value>, score_path: Option<&str>) -> Vec<Record> {
items
.into_iter()
.map(|raw| {
let score = score_path
.and_then(|p| crate::path::resolve(&raw, p).ok())
.and_then(Value::as_f64);
Record { raw, score }
})
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn from_items_resolves_score() {
let items = vec![json!({"score": 0.9}), json!({"score": 0.42})];
let records = Record::from_items(items, Some("score"));
assert_eq!(records.len(), 2);
assert_eq!(records[0].score, Some(0.9));
assert_eq!(records[1].score, Some(0.42));
}
#[test]
fn from_items_handles_missing_path() {
let items = vec![
json!({"score": "high"}),
json!({"other": 1.0}),
json!({"score": 0.5}),
];
let records = Record::from_items(items, Some("score"));
assert_eq!(records[0].score, None);
assert_eq!(records[1].score, None);
assert_eq!(records[2].score, Some(0.5));
let items = vec![json!({"score": 0.9})];
let records = Record::from_items(items, None);
assert_eq!(records[0].score, None);
}
#[test]
fn new_constructs_score_none() {
let r = Record::new(json!({"foo": 1}));
assert!(r.score.is_none());
}
}