tirea_state/lattice/
min_reg.rs

1use serde::{Deserialize, Serialize};
2
3use super::Lattice;
4
5/// A register that merges by taking the minimum value.
6///
7/// Merge semantics: `min(a, b)`.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(transparent)]
10pub struct MinReg<T: Ord>(T);
11
12impl<T: Ord> MinReg<T> {
13    /// Create a new register with the given initial value.
14    pub fn new(value: T) -> Self {
15        Self(value)
16    }
17
18    /// Returns a reference to the current value.
19    pub fn value(&self) -> &T {
20        &self.0
21    }
22
23    /// Set a new value, unconditionally replacing the current one.
24    pub fn set(&mut self, value: T) {
25        self.0 = value;
26    }
27}
28
29impl<T: Ord + Clone + PartialEq> Lattice for MinReg<T> {
30    fn merge(&self, other: &Self) -> Self {
31        if self.0 <= other.0 {
32            self.clone()
33        } else {
34            other.clone()
35        }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use crate::lattice::assert_lattice_laws;
43
44    #[test]
45    fn new_and_value() {
46        let r = MinReg::new(42);
47        assert_eq!(*r.value(), 42);
48    }
49
50    #[test]
51    fn set_replaces() {
52        let mut r = MinReg::new(100);
53        r.set(1);
54        assert_eq!(*r.value(), 1);
55    }
56
57    #[test]
58    fn lattice_laws_i64() {
59        let a = MinReg::new(1i64);
60        let b = MinReg::new(5);
61        let c = MinReg::new(3);
62        assert_lattice_laws(&a, &b, &c);
63
64        let a = MinReg::new(10i64);
65        let b = MinReg::new(10);
66        let c = MinReg::new(7);
67        assert_lattice_laws(&a, &b, &c);
68    }
69
70    #[test]
71    fn lattice_laws_string() {
72        let a = MinReg::new("alpha".to_string());
73        let b = MinReg::new("gamma".to_string());
74        let c = MinReg::new("beta".to_string());
75        assert_lattice_laws(&a, &b, &c);
76    }
77
78    #[test]
79    fn merge_takes_min() {
80        let a = MinReg::new(3);
81        let b = MinReg::new(7);
82        assert_eq!(*a.merge(&b).value(), 3);
83        assert_eq!(*b.merge(&a).value(), 3);
84    }
85
86    #[test]
87    fn merge_equal_values() {
88        let a = MinReg::new(5);
89        let b = MinReg::new(5);
90        assert_eq!(*a.merge(&b).value(), 5);
91    }
92
93    #[test]
94    fn serde_roundtrip() {
95        let r = MinReg::new(42i64);
96        let json = serde_json::to_value(&r).unwrap();
97        assert_eq!(json, serde_json::json!(42));
98
99        let back: MinReg<i64> = serde_json::from_value(json).unwrap();
100        assert_eq!(back, r);
101    }
102
103    #[test]
104    fn serde_string_roundtrip() {
105        let r = MinReg::new("hello".to_string());
106        let json = serde_json::to_value(&r).unwrap();
107        assert_eq!(json, serde_json::json!("hello"));
108
109        let back: MinReg<String> = serde_json::from_value(json).unwrap();
110        assert_eq!(back, r);
111    }
112}