mergable/
context.rs

1pub struct Context<F: crate::SequenceFactory = crate::TimeSequenceFactory> {
2	sequence_factory: F,
3	sequence: F::Sequence,
4	session: Session,
5}
6
7impl Default for Context<crate::TimeSequenceFactory> {
8	fn default() -> Self {
9		Self::new()
10	}
11}
12
13impl<SequenceFactory: crate::SequenceFactory + Default> Context<SequenceFactory> {
14	pub fn new() -> Self {
15		Context {
16			sequence_factory: Default::default(),
17			sequence: SequenceFactory::base(),
18			session: Session::new(),
19		}
20	}
21}
22
23impl<SequenceFactory: crate::SequenceFactory> Context<SequenceFactory> {
24	pub fn next_sequence(&mut self) -> Sequence<SequenceFactory> {
25		let next = self.sequence_factory.acquire(self.sequence.clone());
26		assert!(next > self.sequence);
27
28		self.sequence = next.clone();
29
30		Sequence {
31			value: next,
32			session: self.session.clone(),
33			undo: 0,
34		}
35	}
36
37	/** Start a new session.
38	 *
39	 * This updates the session in this `Context`. This is similar to starting a new `Context` but it ensures that the sequences are still monotonically increasing across sessions which can be important for `Mergable` objects with last-write-wins semantics.
40	 */
41	pub fn new_session(&mut self) {
42		self.session = Session::new();
43	}
44
45	pub fn session(&self) -> Session {
46		self.session.clone()
47	}
48}
49
50pub struct Sequence<SequenceFactory: crate::SequenceFactory> {
51	value: SequenceFactory::Sequence,
52	session: Session,
53	undo: u8,
54}
55
56impl<SequenceFactory: crate::SequenceFactory> Sequence<SequenceFactory> {
57	pub fn zero() -> Self {
58		Sequence {
59			value: SequenceFactory::base(),
60			session: Session(u64::min_value()),
61			undo: 0,
62		}
63	}
64
65	pub fn undo(&self) -> Result<Self, crate::RevertError> {
66		let mut r = self.clone();
67		r.undo = self.undo.checked_add(1)
68			.ok_or(crate::RevertError::TooManyRedos)?;
69		Ok(r)
70	}
71}
72
73impl<T: crate::SequenceFactory> std::fmt::Debug for Sequence<T>
74	where T::Sequence: std::fmt::Debug
75{
76	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
77		let Sequence{value, session, undo} = self;
78		write!(f, "Sequence({:?}, {:?}, {:?})", value, session, undo)
79	}
80}
81
82impl<SequenceFactory: crate::SequenceFactory> Clone for Sequence<SequenceFactory> {
83	fn clone(&self) -> Self {
84		Sequence {
85			value: self.value.clone(),
86			session: self.session.clone(),
87			undo: self.undo,
88		}
89	}
90}
91
92impl<SequenceFactory: crate::SequenceFactory> std::cmp::PartialEq for Sequence<SequenceFactory> {
93	fn eq(&self, that: &Self) -> bool {
94		let Sequence{value, session, undo} = self;
95		(value, session, undo) == (&that.value, &that.session, &that.undo)
96	}
97}
98
99impl<SequenceFactory: crate::SequenceFactory> std::cmp::Eq for Sequence<SequenceFactory> {
100}
101
102impl<SequenceFactory: crate::SequenceFactory> std::cmp::PartialOrd for Sequence<SequenceFactory> {
103	fn partial_cmp(&self, that: &Self) -> Option<std::cmp::Ordering> {
104		let Sequence{value, session, undo} = self;
105		std::cmp::PartialOrd::partial_cmp(
106			&(value, session, undo),
107			&(&that.value, &that.session, &that.undo))
108	}
109}
110
111impl<SequenceFactory: crate::SequenceFactory> std::cmp::Ord for Sequence<SequenceFactory> {
112	fn cmp(&self, that: &Self) -> std::cmp::Ordering {
113		let Sequence{value, session, undo} = self;
114		(value, session, undo).cmp(&(&that.value, &that.session, &that.undo))
115	}
116}
117
118impl<SequenceFactory: crate::SequenceFactory> std::hash::Hash for Sequence<SequenceFactory> {
119	fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
120		let Sequence{value, session, undo} = self;
121		value.hash(h);
122		session.hash(h);
123		undo.hash(h);
124	}
125}
126
127#[derive(Clone,Eq,PartialEq,Hash,Ord,PartialOrd)]
128pub struct Session(u64);
129
130impl Session {
131	pub fn new() -> Self {
132		Self::unsafe_from_u64(rand::Rng::gen(&mut rand::thread_rng()))
133	}
134
135	/// Create a session from the provided value.
136	///
137	/// WARNING: If the same session id is used concurrently it may cause unspecified behaviour including crashes.
138	pub fn unsafe_from_u64(session: u64) -> Self {
139		Session(session)
140	}
141}
142
143impl std::fmt::Debug for Session {
144	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
145		write!(f, "Session({:x})", self.0)
146	}
147}