fix(core,sync,data): deterministic pile serialization, undo skip, url-encode bytes, merge_at

- Derive PartialOrd+Ord on PileType and sort pile entries in pile_map_serde
  before serializing so save-file output is deterministic (M-4)
- Add #[serde(skip)] to undo_stack so transient undo history is never written
  to save files, eliminating unnecessary bloat (M-3)
- Add merge_at() accepting an explicit resolved_at timestamp so callers can
  inject the server-side time; merge() wraps it with Utc::now() for
  backwards compatibility (M-1)
- Fix url_encode to percent-encode UTF-8 bytes rather than Unicode codepoints
  so multi-byte characters produce RFC 3986-compliant output (M-2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-17 20:28:46 -07:00
parent 1eb40433a9
commit 69c6e88188
5 changed files with 53 additions and 35 deletions
+5 -5
View File
@@ -111,12 +111,12 @@ impl MatomoClient {
}
fn url_encode(s: &str) -> String {
s.chars()
.flat_map(|c| match c {
'A'..='Z' | 'a'..='z' | '0'..='9' | '-' | '_' | '.' | '~' => {
vec![c]
s.bytes()
.flat_map(|b| match b {
b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
vec![b as char]
}
c => format!("%{:02X}", c as u32).chars().collect(),
b => format!("%{b:02X}").chars().collect(),
})
.collect()
}