use crate::parser::NodeRef;
use std::collections::HashMap;
#[derive(Clone, Copy, Debug, Default)]
struct NodeMeta {
readability_score: Option<f64>,
is_readability_data_table: bool,
}
#[derive(Default, Debug, Clone)]
pub struct NodeScoreStore {
map: HashMap<usize, NodeMeta>,
}
fn node_key(node: &NodeRef) -> usize {
let ptr: *const _ = &**node;
ptr as usize
}
pub trait NodeScoreExt {
fn readability_score(&self, store: &NodeScoreStore) -> Option<f64>;
fn offset_readability_score(&self, store: &mut NodeScoreStore, offset: f64);
fn set_readability_score(&self, store: &mut NodeScoreStore, value: Option<f64>);
fn is_readability_data_table(&self, store: &NodeScoreStore) -> bool;
fn set_readability_data_table(&self, store: &mut NodeScoreStore, is_readability_data_table: bool);
}
impl NodeScoreExt for NodeRef {
fn readability_score(&self, store: &NodeScoreStore) -> Option<f64> {
let key = node_key(self);
store.map.get(&key).and_then(|m| m.readability_score)
}
fn offset_readability_score(&self, store: &mut NodeScoreStore, offset: f64) {
let key = node_key(self);
let entry = store.map.entry(key).or_default();
entry.readability_score = Some(entry.readability_score.unwrap_or(0.0) + offset);
}
fn set_readability_score(&self, store: &mut NodeScoreStore, value: Option<f64>) {
let key = node_key(self);
let entry = store.map.entry(key).or_default();
entry.readability_score = value;
}
fn is_readability_data_table(&self, store: &NodeScoreStore) -> bool {
let key = node_key(self);
store
.map
.get(&key)
.map(|m| m.is_readability_data_table)
.unwrap_or(false)
}
fn set_readability_data_table(&self, store: &mut NodeScoreStore, is_readability_data_table: bool) {
let key = node_key(self);
let entry = store.map.entry(key).or_default();
entry.is_readability_data_table = is_readability_data_table;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parser::parse_html;
#[test]
fn store_isolated_per_instance() {
let doc = parse_html("<div><p>Hello</p></div>");
let p = doc.select_first("p").unwrap().as_node().clone();
let mut store_a = NodeScoreStore::default();
let mut store_b = NodeScoreStore::default();
p.set_readability_score(&mut store_a, Some(10.0));
assert_eq!(p.readability_score(&store_a), Some(10.0));
assert_eq!(p.readability_score(&store_b), None);
p.set_readability_score(&mut store_b, Some(5.0));
assert_eq!(p.readability_score(&store_a), Some(10.0));
assert_eq!(p.readability_score(&store_b), Some(5.0));
}
}