From 4067bd75fed71422f3a8c14b7d69c43ccf8015ec Mon Sep 17 00:00:00 2001 From: bel Date: Mon, 10 Nov 2025 23:20:01 -0700 Subject: [PATCH] can json diff --- pttodoest/Cargo.lock | 63 ++++++++++++++++++++++++++++++ pttodoest/Cargo.toml | 2 + pttodoest/src/main.rs | 89 ++++++++++++------------------------------- 3 files changed, 90 insertions(+), 64 deletions(-) mode change 100644 => 100755 pttodoest/Cargo.lock mode change 100644 => 100755 pttodoest/Cargo.toml mode change 100644 => 100755 pttodoest/src/main.rs diff --git a/pttodoest/Cargo.lock b/pttodoest/Cargo.lock old mode 100644 new mode 100755 index 26b71c8..6252b7d --- a/pttodoest/Cargo.lock +++ b/pttodoest/Cargo.lock @@ -164,6 +164,28 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "json-patch" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f300e415e2134745ef75f04562dd0145405c2f7fd92065db029ac4b16b57fe90" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonptr" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a3cc660ba5d72bce0b3bb295bf20847ccbb40fd423f3f05b61273672e561fe" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "libc" version = "0.2.177" @@ -176,6 +198,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + [[package]] name = "once_cell_polyfill" version = "1.70.2" @@ -197,7 +225,9 @@ version = "0.1.0" dependencies = [ "clap", "gethostname", + "json-patch", "serde", + "serde_json", "serde_yaml", ] @@ -259,6 +289,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -289,6 +332,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.22" diff --git a/pttodoest/Cargo.toml b/pttodoest/Cargo.toml old mode 100644 new mode 100755 index a6f1f81..5678da7 --- a/pttodoest/Cargo.toml +++ b/pttodoest/Cargo.toml @@ -6,5 +6,7 @@ edition = "2024" [dependencies] clap = { version = "4.5.51", features = ["derive"] } gethostname = "1.1.0" +json-patch = "4.1.0" serde = { version = "1.0.228", features = ["serde_derive"] } +serde_json = "1.0.145" serde_yaml = "0.9.34" diff --git a/pttodoest/src/main.rs b/pttodoest/src/main.rs old mode 100644 new mode 100755 index c49d5f7..d9f1138 --- a/pttodoest/src/main.rs +++ b/pttodoest/src/main.rs @@ -1,6 +1,7 @@ use clap::Parser; use serde_yaml; -use std::io::Read; +use std::io::{Read, Write}; +use serde::{Serialize, Deserialize}; fn main() { for file in Flags::new() @@ -100,27 +101,16 @@ impl File { } fn reconcile_snapshot_changes(&self) -> Result<(), String> { - let history = self.events()?.snapshot()?; - let cached = self.snapshot()?; - match history == cached { - true => Ok(()), - false => { - for task in history.iter() { - if !cached.contains(task) { - self.pop(task.clone())?; - } - } - for i in 0..cached.len() { - if !history.contains(&cached[i]) { - self.push(TaskAt { - task: cached[i].clone(), - at: i, - })?; - } - } - panic!("not impl") - } - } + let snapshot = self.events()?.snapshot()?; + let snapshot = serde_json::to_string(&snapshot).unwrap(); + let snapshot: serde_json::Value = serde_json::from_str(snapshot.as_str()).unwrap(); + + let stage = self.snapshot()?; + let stage = serde_json::to_string(&stage).unwrap(); + let stage: serde_json::Value = serde_json::from_str(stage.as_str()).unwrap(); + + let patch = json_patch::diff(&snapshot, &stage); + panic!("not impl jsondiff snapshots: {:?}", patch) } fn snapshot(&self) -> Result, String> { @@ -147,47 +137,36 @@ impl File { Ok(result) } - fn push(&self, task_at: TaskAt) -> Result<(), String> { - self.append(Delta { - pushed_at: vec![task_at], - popped: vec![], - }) - } - - fn pop(&self, task: Task) -> Result<(), String> { - self.append(Delta { - pushed_at: vec![], - popped: vec![task], - }) - } - fn append(&self, delta: Delta) -> Result<(), String> { use std::fs::OpenOptions; let hostname = gethostname::gethostname(); - let mut file = match OpenOptions::new().write(true).append(true).open(&self.file) { + let log = format!("{}{}", Events::log_prefix(&self.file), gethostname::gethostname().into_string().unwrap()); + let mut file = match OpenOptions::new().write(true).append(true).open(&log) { Ok(f) => Ok(f), Err(msg) => Err(format!( "failed to open {} for appending: {}", &self.file, msg )), }?; - panic!("not impl: {:?}", file) + let line = serde_json::to_string(&delta).unwrap(); + match + writeln!(file, "{}", line) { + Ok(_) => Ok(()), + Err(msg) => Err(format!("failed to append: {}", msg)), + } } } -#[derive(Debug, Clone)] -struct Delta { - pushed_at: Vec, - popped: Vec, -} +#[derive(Debug, Clone, Serialize, Deserialize)] +struct Delta(json_patch::Patch); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] struct TaskAt { task: Task, at: usize, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] struct Task(serde_yaml::Value); #[derive(Debug, Clone)] @@ -238,25 +217,7 @@ impl Events { fn snapshot(&self) -> Result, String> { let mut result = vec![]; for event in self.0.iter() { - for popped in event.popped.iter() { - for i in (0..result.len()) - .map(|i| i as usize) - .filter(|i| result[*i] == *popped) - { - panic!("not impl") - } - } - for push in event.pushed_at.iter() { - result.insert( - if push.at < result.len() { - push.at - } else { - result.len() - }, - push.task.clone(), - ); - } - panic!("not impl: {:?}", result) + panic!("not impl: {:?}", event) } Ok(result) }