tauri_plugin_widgets/
apply.rs1use serde::{Deserialize, Serialize};
4use std::collections::hash_map::DefaultHasher;
5use std::hash::{Hash, Hasher};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(tag = "reason", rename_all = "camelCase")]
10pub enum SkipReason {
11 Unchanged {
13 hash: u64,
15 },
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(tag = "outcome", rename_all = "camelCase")]
21pub enum ReloadOutcome {
22 Ok,
24 Throttled {
26 #[serde(rename = "remainingSecs")]
28 remaining_secs: u64,
29 },
30 Skipped {
32 why: String,
34 },
35 Failed {
37 error: String,
39 },
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(rename_all = "camelCase")]
46pub struct ApplyOutcome {
47 pub written: bool,
49 pub reload: ReloadOutcome,
51 pub transports: Vec<String>,
53 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub skip: Option<SkipReason>,
56}
57
58impl ApplyOutcome {
59 pub fn unchanged(hash: u64) -> Self {
61 Self {
62 written: false,
63 reload: ReloadOutcome::Skipped {
64 why: "unchanged".into(),
65 },
66 transports: Vec::new(),
67 skip: Some(SkipReason::Unchanged { hash }),
68 }
69 }
70}
71
72pub fn config_content_hash(json: &str) -> u64 {
74 let mut hasher = DefaultHasher::new();
75 json.hash(&mut hasher);
76 hasher.finish()
77}
78
79pub fn throttle_remaining_secs(elapsed_secs: u64, min_interval: u64) -> Option<u64> {
81 if min_interval == 0 || elapsed_secs >= min_interval {
82 None
83 } else {
84 Some(min_interval.saturating_sub(elapsed_secs))
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn unchanged_serializes_camel_case() {
94 let o = ApplyOutcome::unchanged(42);
95 let v = serde_json::to_value(&o).unwrap();
96 assert_eq!(v["written"], false);
97 assert_eq!(v["reload"]["outcome"], "skipped");
98 assert_eq!(v["skip"]["reason"], "unchanged");
99 assert_eq!(v["skip"]["hash"], 42);
100 }
101
102 #[test]
103 fn throttled_remaining_secs_camel() {
104 let r = ReloadOutcome::Throttled {
105 remaining_secs: 840,
106 };
107 let v = serde_json::to_value(&r).unwrap();
108 assert_eq!(v["outcome"], "throttled");
109 assert_eq!(v["remainingSecs"], 840);
110 }
111
112 #[test]
113 fn throttle_remaining_math() {
114 assert_eq!(throttle_remaining_secs(0, 0), None);
115 assert_eq!(throttle_remaining_secs(100, 0), None);
116 assert_eq!(throttle_remaining_secs(60, 900), Some(840));
117 assert_eq!(throttle_remaining_secs(900, 900), None);
118 assert_eq!(throttle_remaining_secs(901, 900), None);
119 }
120
121 #[test]
122 fn same_json_same_hash() {
123 assert_eq!(
124 config_content_hash(r#"{"version":1}"#),
125 config_content_hash(r#"{"version":1}"#)
126 );
127 assert_ne!(
128 config_content_hash(r#"{"version":1}"#),
129 config_content_hash(r#"{"version":2}"#)
130 );
131 }
132}