draft.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. use super::{IClashTemp, IProfiles, IRuntime, IVerge};
  2. use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
  3. use std::sync::Arc;
  4. #[derive(Debug, Clone)]
  5. pub struct Draft<T: Clone + ToOwned> {
  6. inner: Arc<Mutex<(T, Option<T>)>>,
  7. }
  8. macro_rules! draft_define {
  9. ($id: ident) => {
  10. impl Draft<$id> {
  11. #[allow(unused)]
  12. pub fn data(&self) -> MappedMutexGuard<$id> {
  13. MutexGuard::map(self.inner.lock(), |guard| &mut guard.0)
  14. }
  15. pub fn latest(&self) -> MappedMutexGuard<$id> {
  16. MutexGuard::map(self.inner.lock(), |inner| {
  17. if inner.1.is_none() {
  18. &mut inner.0
  19. } else {
  20. inner.1.as_mut().unwrap()
  21. }
  22. })
  23. }
  24. pub fn draft(&self) -> MappedMutexGuard<$id> {
  25. MutexGuard::map(self.inner.lock(), |inner| {
  26. if inner.1.is_none() {
  27. inner.1 = Some(inner.0.clone());
  28. }
  29. inner.1.as_mut().unwrap()
  30. })
  31. }
  32. pub fn apply(&self) -> Option<$id> {
  33. let mut inner = self.inner.lock();
  34. match inner.1.take() {
  35. Some(draft) => {
  36. let old_value = inner.0.to_owned();
  37. inner.0 = draft.to_owned();
  38. Some(old_value)
  39. }
  40. None => None,
  41. }
  42. }
  43. pub fn discard(&self) -> Option<$id> {
  44. let mut inner = self.inner.lock();
  45. inner.1.take()
  46. }
  47. }
  48. impl From<$id> for Draft<$id> {
  49. fn from(data: $id) -> Self {
  50. Draft {
  51. inner: Arc::new(Mutex::new((data, None))),
  52. }
  53. }
  54. }
  55. };
  56. }
  57. // draft_define!(IClash);
  58. draft_define!(IClashTemp);
  59. draft_define!(IProfiles);
  60. draft_define!(IRuntime);
  61. draft_define!(IVerge);
  62. #[test]
  63. fn test_draft() {
  64. let verge = IVerge {
  65. enable_auto_launch: Some(true),
  66. enable_tun_mode: Some(false),
  67. ..IVerge::default()
  68. };
  69. let draft = Draft::from(verge);
  70. assert_eq!(draft.data().enable_auto_launch, Some(true));
  71. assert_eq!(draft.data().enable_tun_mode, Some(false));
  72. assert_eq!(draft.draft().enable_auto_launch, Some(true));
  73. assert_eq!(draft.draft().enable_tun_mode, Some(false));
  74. let mut d = draft.draft();
  75. d.enable_auto_launch = Some(false);
  76. d.enable_tun_mode = Some(true);
  77. drop(d);
  78. assert_eq!(draft.data().enable_auto_launch, Some(true));
  79. assert_eq!(draft.data().enable_tun_mode, Some(false));
  80. assert_eq!(draft.draft().enable_auto_launch, Some(false));
  81. assert_eq!(draft.draft().enable_tun_mode, Some(true));
  82. assert_eq!(draft.latest().enable_auto_launch, Some(false));
  83. assert_eq!(draft.latest().enable_tun_mode, Some(true));
  84. assert!(draft.apply().is_some());
  85. assert!(draft.apply().is_none());
  86. assert_eq!(draft.data().enable_auto_launch, Some(false));
  87. assert_eq!(draft.data().enable_tun_mode, Some(true));
  88. assert_eq!(draft.draft().enable_auto_launch, Some(false));
  89. assert_eq!(draft.draft().enable_tun_mode, Some(true));
  90. let mut d = draft.draft();
  91. d.enable_auto_launch = Some(true);
  92. drop(d);
  93. assert_eq!(draft.data().enable_auto_launch, Some(false));
  94. assert_eq!(draft.draft().enable_auto_launch, Some(true));
  95. assert!(draft.discard().is_some());
  96. assert_eq!(draft.data().enable_auto_launch, Some(false));
  97. assert!(draft.discard().is_none());
  98. assert_eq!(draft.draft().enable_auto_launch, Some(false));
  99. }