123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- use super::{IClashTemp, IProfiles, IRuntime, IVerge};
- use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
- use std::sync::Arc;
- #[derive(Debug, Clone)]
- pub struct Draft<T: Clone + ToOwned> {
- inner: Arc<Mutex<(T, Option<T>)>>,
- }
- macro_rules! draft_define {
- ($id: ident) => {
- impl Draft<$id> {
- #[allow(unused)]
- pub fn data(&self) -> MappedMutexGuard<$id> {
- MutexGuard::map(self.inner.lock(), |guard| &mut guard.0)
- }
- pub fn latest(&self) -> MappedMutexGuard<$id> {
- MutexGuard::map(self.inner.lock(), |inner| {
- if inner.1.is_none() {
- &mut inner.0
- } else {
- inner.1.as_mut().unwrap()
- }
- })
- }
- pub fn draft(&self) -> MappedMutexGuard<$id> {
- MutexGuard::map(self.inner.lock(), |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!(IClash);
- draft_define!(IClashTemp);
- draft_define!(IProfiles);
- draft_define!(IRuntime);
- draft_define!(IVerge);
- #[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_eq!(draft.latest().enable_auto_launch, Some(false));
- assert_eq!(draft.latest().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));
- }
|