GyDi 2 роки тому
батько
коміт
09965f1cc6
1 змінених файлів з 112 додано та 0 видалено
  1. 112 0
      src-tauri/src/config/draft.rs

+ 112 - 0
src-tauri/src/config/draft.rs

@@ -0,0 +1,112 @@
+use super::{IProfiles, IVerge};
+use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
+use serde_yaml::Mapping;
+use std::sync::Arc;
+
+#[derive(Debug)]
+pub struct Draft<T: Clone + ToOwned> {
+    inner: Arc<Mutex<(T, Option<T>)>>,
+}
+
+macro_rules! draft_define {
+    ($id: ident) => {
+        impl Draft<$id> {
+            pub fn data(&self) -> MappedMutexGuard<$id> {
+                MutexGuard::map(self.inner.lock(), |guard| &mut guard.0)
+            }
+
+            pub fn draft(&self) -> MappedMutexGuard<$id> {
+                MutexGuard::map(self.inner.lock(), |mut inner| {
+                    if inner.1.is_none() {
+                        inner.1 = Some(inner.0.clone());
+                    }
+
+                    inner.1.as_mut().unwrap()
+                })
+            }
+
+            pub fn apply(&self) -> Option<$id> {
+                let mut inner = self.inner.lock();
+
+                match inner.1.take() {
+                    Some(draft) => {
+                        let old_value = inner.0.to_owned();
+                        inner.0 = draft.to_owned();
+                        Some(old_value)
+                    }
+                    None => None,
+                }
+            }
+
+            pub fn discard(&self) -> Option<$id> {
+                let mut inner = self.inner.lock();
+                inner.1.take()
+            }
+        }
+
+        impl From<$id> for Draft<$id> {
+            fn from(data: $id) -> Self {
+                Draft {
+                    inner: Arc::new(Mutex::new((data, None))),
+                }
+            }
+        }
+    };
+}
+
+draft_define!(IVerge);
+draft_define!(Mapping);
+draft_define!(IProfiles);
+
+#[test]
+fn test_draft() {
+    let verge = IVerge {
+        enable_auto_launch: Some(true),
+        enable_tun_mode: Some(false),
+        ..IVerge::default()
+    };
+
+    let draft = Draft::from(verge);
+
+    assert_eq!(draft.data().enable_auto_launch, Some(true));
+    assert_eq!(draft.data().enable_tun_mode, Some(false));
+
+    assert_eq!(draft.draft().enable_auto_launch, Some(true));
+    assert_eq!(draft.draft().enable_tun_mode, Some(false));
+
+    let mut d = draft.draft();
+    d.enable_auto_launch = Some(false);
+    d.enable_tun_mode = Some(true);
+    drop(d);
+
+    assert_eq!(draft.data().enable_auto_launch, Some(true));
+    assert_eq!(draft.data().enable_tun_mode, Some(false));
+
+    assert_eq!(draft.draft().enable_auto_launch, Some(false));
+    assert_eq!(draft.draft().enable_tun_mode, Some(true));
+
+    assert!(draft.apply().is_some());
+    assert!(draft.apply().is_none());
+
+    assert_eq!(draft.data().enable_auto_launch, Some(false));
+    assert_eq!(draft.data().enable_tun_mode, Some(true));
+
+    assert_eq!(draft.draft().enable_auto_launch, Some(false));
+    assert_eq!(draft.draft().enable_tun_mode, Some(true));
+
+    let mut d = draft.draft();
+    d.enable_auto_launch = Some(true);
+    drop(d);
+
+    assert_eq!(draft.data().enable_auto_launch, Some(false));
+
+    assert_eq!(draft.draft().enable_auto_launch, Some(true));
+
+    assert!(draft.discard().is_some());
+
+    assert_eq!(draft.data().enable_auto_launch, Some(false));
+
+    assert!(draft.discard().is_none());
+
+    assert_eq!(draft.draft().enable_auto_launch, Some(false));
+}