Skip to main content

codetether_browser/browser/offline/
cookie_diff.rs

1//! Diff two JSON cookie jars. Keyed on (name, domain, path) via cookie_diff_index.
2//! Any record-level difference counts as `changed`, not just value.
3
4use anyhow::{Context, Result};
5use std::path::Path;
6
7use super::cookie_diff_index::index;
8use super::cookie_parse::CookieRecord;
9
10#[derive(Debug, serde::Serialize)]
11pub struct CookieDelta {
12    pub added: Vec<CookieRecord>,
13    pub removed: Vec<CookieRecord>,
14    pub changed: Vec<Changed>,
15    /// Cookie keys (name|domain|path) that appeared more than once in either input.
16    pub duplicates: Vec<String>,
17}
18
19#[derive(Debug, serde::Serialize)]
20pub struct Changed {
21    pub key: String,
22    pub before: CookieRecord,
23    pub after: CookieRecord,
24}
25
26pub fn run(before_path: &Path, after_path: &Path) -> Result<String> {
27    let before = load(before_path).with_context(|| format!("read {}", before_path.display()))?;
28    let after = load(after_path).with_context(|| format!("read {}", after_path.display()))?;
29    Ok(serde_json::to_string_pretty(&diff(&before, &after))?)
30}
31
32fn load(path: &Path) -> Result<Vec<CookieRecord>> {
33    Ok(serde_json::from_str(&std::fs::read_to_string(path)?)?)
34}
35
36pub fn diff(before: &[CookieRecord], after: &[CookieRecord]) -> CookieDelta {
37    let (bmap, mut duplicates) = index(before);
38    let (amap, adup) = index(after);
39    duplicates.extend(adup);
40    duplicates.sort();
41    duplicates.dedup();
42    let added = amap
43        .iter()
44        .filter(|(k, _)| !bmap.contains_key(*k))
45        .map(|(_, c)| (*c).clone())
46        .collect();
47    let removed = bmap
48        .iter()
49        .filter(|(k, _)| !amap.contains_key(*k))
50        .map(|(_, c)| (*c).clone())
51        .collect();
52    let changed = bmap
53        .iter()
54        .filter_map(|(k, b)| {
55            amap.get(k).and_then(|a| {
56                (a != b).then(|| Changed {
57                    key: k.clone(),
58                    before: (*b).clone(),
59                    after: (*a).clone(),
60                })
61            })
62        })
63        .collect();
64    CookieDelta {
65        added,
66        removed,
67        changed,
68        duplicates,
69    }
70}