loro_internal/
version.rs

1mod frontiers;
2pub use frontiers::Frontiers;
3
4use crate::{
5    id::{Counter, ID},
6    oplog::AppDag,
7    span::{CounterSpan, IdSpan},
8    LoroError, PeerID,
9};
10use loro_common::{HasCounter, HasCounterSpan, HasIdSpan, HasLamportSpan, IdFull, IdSpanVector};
11use rustc_hash::FxHashMap;
12use serde::{Deserialize, Serialize};
13use smallvec::SmallVec;
14use std::{
15    cmp::Ordering,
16    ops::{ControlFlow, Deref, DerefMut},
17};
18
19/// [VersionVector](https://en.wikipedia.org/wiki/Version_vector)
20/// is a map from [PeerID] to [Counter]. Its a right-open interval.
21///
22/// i.e. a [VersionVector] of `{A: 1, B: 2}` means that A has 1 atomic op and B has 2 atomic ops,
23/// thus ID of `{client: A, counter: 1}` is out of the range.
24//
25// NOTE: though normally it doesn't make sense to have an entry with counter = 0, but it can be 0 in certain cases.
26// Like, when using start_vv and end_vv to mark the version range, start_vv may have an entry with counter = 0.
27#[repr(transparent)]
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct VersionVector(FxHashMap<PeerID, Counter>);
30
31#[repr(transparent)]
32#[derive(Debug, Clone, Default, PartialEq, Eq)]
33pub struct VersionRange(pub(crate) FxHashMap<PeerID, (Counter, Counter)>);
34
35#[macro_export]
36macro_rules! version_range {
37    ($($peer:expr => ($start:expr, $end:expr)),* $(,)?) => {{
38        let mut map = ::rustc_hash::FxHashMap::default();
39        $(
40            map.insert($peer, ($start, $end));
41        )*
42        $crate::version::VersionRange::from_map(map)
43    }};
44}
45
46impl VersionRange {
47    pub fn new() -> Self {
48        Self(Default::default())
49    }
50
51    pub fn from_map(map: FxHashMap<PeerID, (Counter, Counter)>) -> Self {
52        Self(map)
53    }
54
55    pub fn iter(&self) -> impl Iterator<Item = (&PeerID, &(Counter, Counter))> + '_ {
56        self.0.iter()
57    }
58
59    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&PeerID, &mut (Counter, Counter))> + '_ {
60        self.0.iter_mut()
61    }
62
63    pub fn clear(&mut self) {
64        self.0.clear()
65    }
66
67    pub fn get(&self, peer: &PeerID) -> Option<&(Counter, Counter)> {
68        self.0.get(peer)
69    }
70
71    pub fn insert(&mut self, peer: PeerID, start: Counter, end: Counter) {
72        self.0.insert(peer, (start, end));
73    }
74
75    pub fn from_vv(vv: &VersionVector) -> Self {
76        let mut ans = Self::new();
77        for (peer, counter) in vv.iter() {
78            ans.insert(*peer, 0, *counter);
79        }
80        ans
81    }
82
83    pub fn contains_ops_between(&self, vv_a: &VersionVector, vv_b: &VersionVector) -> bool {
84        for span in vv_a.sub_iter(vv_b) {
85            if !self.contains_id_span(IdSpan::new(
86                span.peer,
87                span.counter.start.saturating_sub(1),
88                span.counter.end,
89            )) {
90                return false;
91            }
92        }
93
94        for span in vv_b.sub_iter(vv_a) {
95            if !self.contains_id_span(IdSpan::new(
96                span.peer,
97                span.counter.start.saturating_sub(1),
98                span.counter.end,
99            )) {
100                return false;
101            }
102        }
103
104        true
105    }
106
107    pub fn has_overlap_with(&self, mut span: IdSpan) -> bool {
108        span.normalize_();
109        if let Some((start, end)) = self.get(&span.peer) {
110            start < &span.counter.end && end > &span.counter.start
111        } else {
112            false
113        }
114    }
115
116    pub fn contains_id(&self, id: ID) -> bool {
117        if let Some((start, end)) = self.get(&id.peer) {
118            start <= &id.counter && end > &id.counter
119        } else {
120            false
121        }
122    }
123
124    pub fn contains_id_span(&self, mut span: IdSpan) -> bool {
125        span.normalize_();
126        if let Some((start, end)) = self.get(&span.peer) {
127            start <= &span.counter.start && end >= &span.counter.end
128        } else {
129            false
130        }
131    }
132
133    pub fn extends_to_include_id_span(&mut self, mut span: IdSpan) {
134        span.normalize_();
135        if let Some((start, end)) = self.0.get_mut(&span.peer) {
136            *start = (*start).min(span.counter.start);
137            *end = (*end).max(span.counter.end);
138        } else {
139            self.insert(span.peer, span.counter.start, span.counter.end);
140        }
141    }
142
143    pub fn is_empty(&self) -> bool {
144        self.0.is_empty()
145    }
146
147    pub fn inner(&self) -> &FxHashMap<PeerID, (Counter, Counter)> {
148        &self.0
149    }
150}
151
152/// Immutable version vector
153///
154/// It has O(1) clone time and O(logN) insert/delete/lookup time.
155///
156/// It's more memory efficient than [VersionVector] when the version vector
157/// can be created from cloning and modifying other similar version vectors.
158#[repr(transparent)]
159#[derive(Debug, Clone, Default, Serialize, Deserialize)]
160pub struct ImVersionVector(im::HashMap<PeerID, Counter, rustc_hash::FxBuildHasher>);
161
162impl ImVersionVector {
163    pub fn new() -> Self {
164        Self(Default::default())
165    }
166
167    pub fn clear(&mut self) {
168        self.0.clear()
169    }
170
171    pub fn get(&self, key: &PeerID) -> Option<&Counter> {
172        self.0.get(key)
173    }
174
175    pub fn get_mut(&mut self, key: &PeerID) -> Option<&mut Counter> {
176        self.0.get_mut(key)
177    }
178
179    pub fn insert(&mut self, k: PeerID, v: Counter) {
180        self.0.insert(k, v);
181    }
182
183    pub fn is_empty(&self) -> bool {
184        self.0.is_empty()
185    }
186
187    pub fn iter(&self) -> im::hashmap::Iter<'_, PeerID, Counter> {
188        self.0.iter()
189    }
190
191    pub fn remove(&mut self, k: &PeerID) -> Option<Counter> {
192        self.0.remove(k)
193    }
194
195    pub fn len(&self) -> usize {
196        self.0.len()
197    }
198
199    pub fn contains_key(&self, k: &PeerID) -> bool {
200        self.0.contains_key(k)
201    }
202
203    pub fn encode(&self) -> Vec<u8> {
204        postcard::to_allocvec(self).unwrap()
205    }
206
207    pub fn decode(bytes: &[u8]) -> Result<Self, LoroError> {
208        let vv = VersionVector::decode(bytes)?;
209        Ok(Self::from_vv(&vv))
210    }
211
212    pub fn to_vv(&self) -> VersionVector {
213        VersionVector(self.0.iter().map(|(&k, &v)| (k, v)).collect())
214    }
215
216    pub fn from_vv(vv: &VersionVector) -> Self {
217        ImVersionVector(vv.0.iter().map(|(&k, &v)| (k, v)).collect())
218    }
219
220    pub fn extend_to_include_vv<'a>(
221        &mut self,
222        vv: impl Iterator<Item = (&'a PeerID, &'a Counter)>,
223    ) {
224        for (&client_id, &counter) in vv {
225            if let Some(my_counter) = self.0.get_mut(&client_id) {
226                if *my_counter < counter {
227                    *my_counter = counter;
228                }
229            } else {
230                self.0.insert(client_id, counter);
231            }
232        }
233    }
234
235    #[inline]
236    pub fn merge(&mut self, other: &Self) {
237        self.extend_to_include_vv(other.0.iter());
238    }
239
240    #[inline]
241    pub fn merge_vv(&mut self, other: &VersionVector) {
242        self.extend_to_include_vv(other.0.iter());
243    }
244
245    #[inline]
246    pub fn set_last(&mut self, id: ID) {
247        self.0.insert(id.peer, id.counter + 1);
248    }
249
250    pub fn extend_to_include_last_id(&mut self, id: ID) {
251        if let Some(counter) = self.0.get_mut(&id.peer) {
252            if *counter <= id.counter {
253                *counter = id.counter + 1;
254            }
255        } else {
256            self.set_last(id)
257        }
258    }
259
260    pub(crate) fn includes_id(&self, x: ID) -> bool {
261        if self.is_empty() {
262            return false;
263        }
264
265        self.get(&x.peer).copied().unwrap_or(0) > x.counter
266    }
267}
268
269impl PartialEq for VersionVector {
270    fn eq(&self, other: &Self) -> bool {
271        self.iter()
272            .all(|(client, counter)| other.get(client).unwrap_or(&0) == counter)
273            && other
274                .iter()
275                .all(|(client, counter)| self.get(client).unwrap_or(&0) == counter)
276    }
277}
278
279impl Eq for VersionVector {}
280
281impl PartialEq for ImVersionVector {
282    fn eq(&self, other: &Self) -> bool {
283        self.0
284            .iter()
285            .all(|(client, counter)| other.0.get(client).unwrap_or(&0) == counter)
286            && other
287                .0
288                .iter()
289                .all(|(client, counter)| self.0.get(client).unwrap_or(&0) == counter)
290    }
291}
292
293impl Eq for ImVersionVector {}
294
295impl Deref for VersionVector {
296    type Target = FxHashMap<PeerID, Counter>;
297
298    fn deref(&self) -> &Self::Target {
299        &self.0
300    }
301}
302
303#[derive(Default, Debug, PartialEq, Eq)]
304pub struct VersionVectorDiff {
305    /// The spans that the `left` side needs to retreat to reach the `right` side
306    ///
307    /// these spans are included in the left, but not in the right
308    pub retreat: IdSpanVector,
309    /// The spans that the `left` side needs to forward to reach the `right` side
310    ///
311    /// these spans are included in the right, but not in the left
312    pub forward: IdSpanVector,
313}
314
315impl VersionVectorDiff {
316    #[inline]
317    pub fn merge_left(&mut self, span: IdSpan) {
318        merge(&mut self.retreat, span);
319    }
320
321    #[inline]
322    pub fn merge_right(&mut self, span: IdSpan) {
323        merge(&mut self.forward, span);
324    }
325
326    #[inline]
327    pub fn subtract_start_left(&mut self, span: IdSpan) {
328        subtract_start(&mut self.retreat, span);
329    }
330
331    #[inline]
332    pub fn subtract_start_right(&mut self, span: IdSpan) {
333        subtract_start(&mut self.forward, span);
334    }
335
336    pub fn get_id_spans_left(&self) -> impl Iterator<Item = IdSpan> + '_ {
337        self.retreat.iter().map(|(peer, span)| IdSpan {
338            peer: *peer,
339            counter: *span,
340        })
341    }
342
343    pub fn get_id_spans_right(&self) -> impl Iterator<Item = IdSpan> + '_ {
344        self.forward.iter().map(|(peer, span)| IdSpan {
345            peer: *peer,
346            counter: *span,
347        })
348    }
349}
350
351fn subtract_start(m: &mut FxHashMap<PeerID, CounterSpan>, target: IdSpan) {
352    if let Some(span) = m.get_mut(&target.peer) {
353        if span.start < target.counter.end {
354            span.start = target.counter.end;
355        }
356    }
357}
358
359fn merge(m: &mut FxHashMap<PeerID, CounterSpan>, mut target: IdSpan) {
360    target.normalize_();
361    if let Some(span) = m.get_mut(&target.peer) {
362        span.start = span.start.min(target.counter.start);
363        span.end = span.end.max(target.counter.end);
364    } else {
365        m.insert(target.peer, target.counter);
366    }
367}
368
369impl PartialOrd for VersionVector {
370    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
371        let mut self_greater = true;
372        let mut other_greater = true;
373        let mut eq = true;
374        for (client_id, other_end) in other.iter() {
375            if let Some(self_end) = self.get(client_id) {
376                if self_end < other_end {
377                    self_greater = false;
378                    eq = false;
379                }
380                if self_end > other_end {
381                    other_greater = false;
382                    eq = false;
383                }
384            } else if *other_end > 0 {
385                self_greater = false;
386                eq = false;
387            }
388        }
389
390        for (client_id, self_end) in self.iter() {
391            if other.contains_key(client_id) {
392                continue;
393            } else if *self_end > 0 {
394                other_greater = false;
395                eq = false;
396            }
397        }
398
399        if eq {
400            Some(Ordering::Equal)
401        } else if self_greater {
402            Some(Ordering::Greater)
403        } else if other_greater {
404            Some(Ordering::Less)
405        } else {
406            None
407        }
408    }
409}
410
411impl PartialOrd for ImVersionVector {
412    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
413        let mut self_greater = true;
414        let mut other_greater = true;
415        let mut eq = true;
416        for (client_id, other_end) in other.iter() {
417            if let Some(self_end) = self.get(client_id) {
418                if self_end < other_end {
419                    self_greater = false;
420                    eq = false;
421                }
422                if self_end > other_end {
423                    other_greater = false;
424                    eq = false;
425                }
426            } else if *other_end > 0 {
427                self_greater = false;
428                eq = false;
429            }
430        }
431
432        for (client_id, self_end) in self.iter() {
433            if other.contains_key(client_id) {
434                continue;
435            } else if *self_end > 0 {
436                other_greater = false;
437                eq = false;
438            }
439        }
440
441        if eq {
442            Some(Ordering::Equal)
443        } else if self_greater {
444            Some(Ordering::Greater)
445        } else if other_greater {
446            Some(Ordering::Less)
447        } else {
448            None
449        }
450    }
451}
452
453impl DerefMut for VersionVector {
454    fn deref_mut(&mut self) -> &mut Self::Target {
455        &mut self.0
456    }
457}
458
459impl VersionVector {
460    pub fn diff(&self, rhs: &Self) -> VersionVectorDiff {
461        let mut ans: VersionVectorDiff = Default::default();
462        for (client_id, &counter) in self.iter() {
463            if let Some(&rhs_counter) = rhs.get(client_id) {
464                match counter.cmp(&rhs_counter) {
465                    Ordering::Less => {
466                        ans.forward.insert(
467                            *client_id,
468                            CounterSpan {
469                                start: counter,
470                                end: rhs_counter,
471                            },
472                        );
473                    }
474                    Ordering::Greater => {
475                        ans.retreat.insert(
476                            *client_id,
477                            CounterSpan {
478                                start: rhs_counter,
479                                end: counter,
480                            },
481                        );
482                    }
483                    Ordering::Equal => {}
484                }
485            } else {
486                ans.retreat.insert(
487                    *client_id,
488                    CounterSpan {
489                        start: 0,
490                        end: counter,
491                    },
492                );
493            }
494        }
495        for (client_id, &rhs_counter) in rhs.iter() {
496            if !self.contains_key(client_id) {
497                ans.forward.insert(
498                    *client_id,
499                    CounterSpan {
500                        start: 0,
501                        end: rhs_counter,
502                    },
503                );
504            }
505        }
506
507        ans
508    }
509
510    /// Returns two iterators that cover the differences between two version vectors.
511    ///
512    /// - The first iterator contains the spans that are in `self` but not in `rhs`
513    /// - The second iterator contains the spans that are in `rhs` but not in `self`
514    pub fn diff_iter<'a>(
515        &'a self,
516        rhs: &'a Self,
517    ) -> (
518        impl Iterator<Item = IdSpan> + 'a,
519        impl Iterator<Item = IdSpan> + 'a,
520    ) {
521        (self.sub_iter(rhs), rhs.sub_iter(self))
522    }
523
524    /// Returns the spans that are in `self` but not in `rhs`
525    pub fn sub_iter<'a>(&'a self, rhs: &'a Self) -> impl Iterator<Item = IdSpan> + 'a {
526        self.iter().filter_map(move |(peer, &counter)| {
527            if let Some(&rhs_counter) = rhs.get(peer) {
528                if counter > rhs_counter {
529                    Some(IdSpan {
530                        peer: *peer,
531                        counter: CounterSpan {
532                            start: rhs_counter,
533                            end: counter,
534                        },
535                    })
536                } else {
537                    None
538                }
539            } else if counter > 0 {
540                Some(IdSpan {
541                    peer: *peer,
542                    counter: CounterSpan {
543                        start: 0,
544                        end: counter,
545                    },
546                })
547            } else {
548                None
549            }
550        })
551    }
552
553    /// Returns the spans that are in `self` but not in `rhs`
554    pub fn sub_iter_im<'a>(
555        &'a self,
556        rhs: &'a ImVersionVector,
557    ) -> impl Iterator<Item = IdSpan> + 'a {
558        self.iter().filter_map(move |(peer, &counter)| {
559            if let Some(&rhs_counter) = rhs.get(peer) {
560                if counter > rhs_counter {
561                    Some(IdSpan {
562                        peer: *peer,
563                        counter: CounterSpan {
564                            start: rhs_counter,
565                            end: counter,
566                        },
567                    })
568                } else {
569                    None
570                }
571            } else if counter > 0 {
572                Some(IdSpan {
573                    peer: *peer,
574                    counter: CounterSpan {
575                        start: 0,
576                        end: counter,
577                    },
578                })
579            } else {
580                None
581            }
582        })
583    }
584
585    /// Iter all span from a -> b and b -> a
586    pub fn iter_between<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = IdSpan> + 'a {
587        // PERF: can be optimized a little
588        self.sub_iter(other).chain(other.sub_iter(self))
589    }
590
591    pub fn sub_vec(&self, rhs: &Self) -> IdSpanVector {
592        self.sub_iter(rhs).map(|x| (x.peer, x.counter)).collect()
593    }
594
595    pub fn distance_between(&self, other: &Self) -> usize {
596        let mut ans = 0;
597        for (client_id, &counter) in self.iter() {
598            if let Some(&other_counter) = other.get(client_id) {
599                ans += (counter - other_counter).abs();
600            } else if counter > 0 {
601                ans += counter;
602            }
603        }
604
605        for (client_id, &counter) in other.iter() {
606            if !self.contains_key(client_id) {
607                ans += counter;
608            }
609        }
610
611        ans as usize
612    }
613
614    pub fn to_spans(&self) -> IdSpanVector {
615        self.iter()
616            .map(|(client_id, &counter)| {
617                (
618                    *client_id,
619                    CounterSpan {
620                        start: 0,
621                        end: counter,
622                    },
623                )
624            })
625            .collect()
626    }
627
628    #[inline]
629    pub fn get_frontiers(&self) -> Frontiers {
630        self.iter()
631            .filter_map(|(client_id, &counter)| {
632                if counter > 0 {
633                    Some(ID {
634                        peer: *client_id,
635                        counter: counter - 1,
636                    })
637                } else {
638                    None
639                }
640            })
641            .collect()
642    }
643
644    #[inline]
645    pub fn new() -> Self {
646        Self(Default::default())
647    }
648
649    /// set the inclusive ending point. target id will be included by self
650    #[inline]
651    pub fn set_last(&mut self, id: ID) {
652        self.0.insert(id.peer, id.counter + 1);
653    }
654
655    #[inline]
656    pub fn get_last(&self, client_id: PeerID) -> Option<Counter> {
657        self.0
658            .get(&client_id)
659            .and_then(|&x| if x == 0 { None } else { Some(x - 1) })
660    }
661
662    /// set the exclusive ending point. target id will NOT be included by self
663    #[inline]
664    pub fn set_end(&mut self, id: ID) {
665        if id.counter <= 0 {
666            self.0.remove(&id.peer);
667        } else {
668            self.0.insert(id.peer, id.counter);
669        }
670    }
671
672    /// Update the end counter of the given client if the end is greater.
673    /// Return whether updated
674    #[inline]
675    pub fn try_update_last(&mut self, id: ID) -> bool {
676        if let Some(end) = self.0.get_mut(&id.peer) {
677            if *end < id.counter + 1 {
678                *end = id.counter + 1;
679                true
680            } else {
681                false
682            }
683        } else {
684            self.0.insert(id.peer, id.counter + 1);
685            true
686        }
687    }
688
689    pub fn get_missing_span(&self, target: &Self) -> Vec<IdSpan> {
690        let mut ans = vec![];
691        for (client_id, other_end) in target.iter() {
692            if let Some(my_end) = self.get(client_id) {
693                if my_end < other_end {
694                    ans.push(IdSpan::new(*client_id, *my_end, *other_end));
695                }
696            } else {
697                ans.push(IdSpan::new(*client_id, 0, *other_end));
698            }
699        }
700
701        ans
702    }
703
704    pub fn merge(&mut self, other: &Self) {
705        for (&client_id, &other_end) in other.iter() {
706            if let Some(my_end) = self.get_mut(&client_id) {
707                if *my_end < other_end {
708                    *my_end = other_end;
709                }
710            } else {
711                self.0.insert(client_id, other_end);
712            }
713        }
714    }
715
716    pub fn includes_vv(&self, other: &VersionVector) -> bool {
717        match self.partial_cmp(other) {
718            Some(ord) => match ord {
719                Ordering::Less => false,
720                Ordering::Equal => true,
721                Ordering::Greater => true,
722            },
723            None => false,
724        }
725    }
726
727    pub fn includes_id(&self, id: ID) -> bool {
728        if let Some(end) = self.get(&id.peer) {
729            if *end > id.counter {
730                return true;
731            }
732        }
733        false
734    }
735
736    pub fn intersect_span(&self, target: IdSpan) -> Option<CounterSpan> {
737        if let Some(&end) = self.get(&target.peer) {
738            if end > target.ctr_start() {
739                let count_end = target.ctr_end();
740                return Some(CounterSpan {
741                    start: target.ctr_start(),
742                    end: end.min(count_end),
743                });
744            }
745        }
746
747        None
748    }
749
750    pub fn extend_to_include_vv<'a>(
751        &mut self,
752        vv: impl Iterator<Item = (&'a PeerID, &'a Counter)>,
753    ) {
754        for (&client_id, &counter) in vv {
755            if let Some(my_counter) = self.get_mut(&client_id) {
756                if *my_counter < counter {
757                    *my_counter = counter;
758                }
759            } else {
760                self.0.insert(client_id, counter);
761            }
762        }
763    }
764
765    pub fn extend_to_include_last_id(&mut self, id: ID) {
766        if let Some(counter) = self.get_mut(&id.peer) {
767            if *counter <= id.counter {
768                *counter = id.counter + 1;
769            }
770        } else {
771            self.set_last(id)
772        }
773    }
774
775    pub fn extend_to_include_end_id(&mut self, id: ID) {
776        if let Some(counter) = self.get_mut(&id.peer) {
777            if *counter < id.counter {
778                *counter = id.counter;
779            }
780        } else {
781            self.set_end(id)
782        }
783    }
784
785    pub fn extend_to_include(&mut self, span: IdSpan) {
786        if let Some(counter) = self.get_mut(&span.peer) {
787            if *counter < span.counter.norm_end() {
788                *counter = span.counter.norm_end();
789            }
790        } else {
791            self.insert(span.peer, span.counter.norm_end());
792        }
793    }
794
795    pub fn shrink_to_exclude(&mut self, span: IdSpan) {
796        if span.counter.min() == 0 {
797            self.remove(&span.peer);
798            return;
799        }
800
801        if let Some(counter) = self.get_mut(&span.peer) {
802            if *counter > span.counter.min() {
803                *counter = span.counter.min();
804            }
805        }
806    }
807
808    pub fn forward(&mut self, spans: &IdSpanVector) {
809        for span in spans.iter() {
810            self.extend_to_include(IdSpan {
811                peer: *span.0,
812                counter: *span.1,
813            });
814        }
815    }
816
817    pub fn retreat(&mut self, spans: &IdSpanVector) {
818        for span in spans.iter() {
819            self.shrink_to_exclude(IdSpan {
820                peer: *span.0,
821                counter: *span.1,
822            });
823        }
824    }
825
826    pub fn intersection(&self, other: &VersionVector) -> VersionVector {
827        let mut ans = VersionVector::new();
828        for (client_id, &counter) in self.iter() {
829            if let Some(&other_counter) = other.get(client_id) {
830                if counter < other_counter {
831                    if counter != 0 {
832                        ans.insert(*client_id, counter);
833                    }
834                } else if other_counter != 0 {
835                    ans.insert(*client_id, other_counter);
836                }
837            }
838        }
839        ans
840    }
841
842    #[inline(always)]
843    pub fn encode(&self) -> Vec<u8> {
844        postcard::to_allocvec(self).unwrap()
845    }
846
847    #[inline(always)]
848    pub fn decode(bytes: &[u8]) -> Result<Self, LoroError> {
849        postcard::from_bytes(bytes).map_err(|_| LoroError::DecodeVersionVectorError)
850    }
851
852    pub fn to_im_vv(&self) -> ImVersionVector {
853        ImVersionVector(self.0.iter().map(|(&k, &v)| (k, v)).collect())
854    }
855
856    pub fn from_im_vv(im_vv: &ImVersionVector) -> Self {
857        VersionVector(im_vv.0.iter().map(|(&k, &v)| (k, v)).collect())
858    }
859}
860
861/// Use minimal set of ids to represent the frontiers
862#[tracing::instrument(skip(dag))]
863pub fn shrink_frontiers(last_ids: &Frontiers, dag: &AppDag) -> Result<Frontiers, ID> {
864    // it only keep the ids of ops that are concurrent to each other
865
866    if last_ids.len() <= 1 {
867        return Ok(last_ids.clone());
868    }
869
870    let mut last_ids = {
871        let ids = filter_duplicated_peer_id(last_ids);
872        if last_ids.len() == 1 {
873            let mut frontiers = Frontiers::default();
874            frontiers.push(last_ids.as_single().unwrap());
875            return Ok(frontiers);
876        }
877
878        let mut last_ids = Vec::with_capacity(ids.len());
879        for id in ids {
880            let Some(lamport) = dag.get_lamport(&id) else {
881                return Err(id);
882            };
883            last_ids.push(IdFull::new(id.peer, id.counter, lamport))
884        }
885
886        last_ids
887    };
888
889    let mut frontiers = Vec::new();
890    // Iterate from the greatest lamport to the smallest
891    last_ids.sort_by_key(|x| x.lamport);
892    for id in last_ids.iter().rev() {
893        let mut should_insert = true;
894        let mut len = 0;
895        // travel backward because they have more similar lamport
896        for f_id in frontiers.iter().rev() {
897            dag.travel_ancestors(*f_id, &mut |x| {
898                len += 1;
899                if x.contains_id(id.id()) {
900                    should_insert = false;
901                    ControlFlow::Break(())
902                } else if x.lamport_last() < id.lamport {
903                    // Already travel to a node with smaller lamport, no need to continue, we are sure two ops are concurrent now
904                    ControlFlow::Break(())
905                } else {
906                    ControlFlow::Continue(())
907                }
908            });
909        }
910
911        if should_insert {
912            frontiers.push(id.id());
913        }
914    }
915
916    Ok(frontiers.into())
917}
918
919fn filter_duplicated_peer_id(last_ids: &Frontiers) -> Vec<ID> {
920    let mut peer_max_counters = FxHashMap::default();
921    for id in last_ids.iter() {
922        let counter = peer_max_counters.entry(id.peer).or_insert(id.counter);
923        if id.counter > *counter {
924            *counter = id.counter;
925        }
926    }
927
928    peer_max_counters
929        .into_iter()
930        .map(|(peer, counter)| ID::new(peer, counter))
931        .collect()
932}
933
934impl Default for VersionVector {
935    fn default() -> Self {
936        Self::new()
937    }
938}
939
940impl From<FxHashMap<PeerID, Counter>> for VersionVector {
941    fn from(map: FxHashMap<PeerID, Counter>) -> Self {
942        let mut im_map = FxHashMap::default();
943        for (client_id, counter) in map {
944            im_map.insert(client_id, counter);
945        }
946        Self(im_map)
947    }
948}
949
950impl From<Vec<ID>> for VersionVector {
951    fn from(vec: Vec<ID>) -> Self {
952        let mut vv = VersionVector::new();
953        for id in vec {
954            vv.set_last(id);
955        }
956
957        vv
958    }
959}
960
961impl FromIterator<ID> for VersionVector {
962    fn from_iter<T: IntoIterator<Item = ID>>(iter: T) -> Self {
963        let iter = iter.into_iter();
964        let mut vv = VersionVector(FxHashMap::with_capacity_and_hasher(
965            iter.size_hint().0,
966            Default::default(),
967        ));
968        for id in iter {
969            vv.set_last(id);
970        }
971
972        vv
973    }
974}
975
976impl FromIterator<(PeerID, Counter)> for VersionVector {
977    fn from_iter<T: IntoIterator<Item = (PeerID, Counter)>>(iter: T) -> Self {
978        VersionVector(FxHashMap::from_iter(iter))
979    }
980}
981
982// Note: It will be encoded into binary format, so the order of its fields should not be changed.
983
984pub fn are_frontiers_eq(a: &[ID], b: &[ID]) -> bool {
985    if a.len() != b.len() {
986        return false;
987    }
988
989    let mut a: SmallVec<[ID; 10]> = a.into();
990    let mut b: SmallVec<[ID; 10]> = b.into();
991
992    a.sort();
993    b.sort();
994
995    a == b
996}
997
998#[cfg(test)]
999mod tests {
1000    #![allow(clippy::neg_cmp_op_on_partial_ord)]
1001    use super::*;
1002    mod cmp {
1003        use super::*;
1004        #[test]
1005        fn test() {
1006            let a: VersionVector = vec![ID::new(1, 1), ID::new(2, 2)].into();
1007            let b: VersionVector = vec![ID::new(1, 1), ID::new(2, 2)].into();
1008            assert_eq!(a.partial_cmp(&b), Some(Ordering::Equal));
1009            assert!(a == b);
1010
1011            let a: VersionVector = vec![ID::new(1, 2), ID::new(2, 1)].into();
1012            let b: VersionVector = vec![ID::new(1, 1), ID::new(2, 2)].into();
1013            assert_eq!(a.partial_cmp(&b), None);
1014
1015            assert!(!(a > b));
1016            assert!(!(b > a));
1017            assert!(!(b == a));
1018
1019            let a: VersionVector = vec![ID::new(1, 2), ID::new(2, 3)].into();
1020            let b: VersionVector = vec![ID::new(1, 1), ID::new(2, 2)].into();
1021            assert_eq!(a.partial_cmp(&b), Some(Ordering::Greater));
1022            assert!(a > b);
1023            assert!(a >= b);
1024
1025            let a: VersionVector = vec![ID::new(1, 0), ID::new(2, 2)].into();
1026            let b: VersionVector = vec![ID::new(1, 1), ID::new(2, 2)].into();
1027            assert_eq!(a.partial_cmp(&b), Some(Ordering::Less));
1028            assert!(a < b);
1029            assert!(a <= b);
1030        }
1031    }
1032
1033    #[test]
1034    fn im() {
1035        let mut a = VersionVector::new();
1036        a.set_last(ID::new(1, 1));
1037        a.set_last(ID::new(2, 1));
1038        let mut b = a.clone();
1039        b.merge(&vec![ID::new(1, 2), ID::new(2, 2)].into());
1040        assert!(a != b);
1041        assert_eq!(a.get(&1), Some(&2));
1042        assert_eq!(a.get(&2), Some(&2));
1043        assert_eq!(b.get(&1), Some(&3));
1044        assert_eq!(b.get(&2), Some(&3));
1045    }
1046
1047    #[test]
1048    fn test_encode_decode_im_version_vector() {
1049        let vv = VersionVector::from_iter([(1, 1), (2, 2), (3, 3)]);
1050        let im_vv = vv.to_im_vv();
1051        let decoded_vv = VersionVector::from_im_vv(&im_vv);
1052        assert_eq!(vv, decoded_vv);
1053    }
1054
1055    #[test]
1056    fn test_version_vector_encoding_decoding() {
1057        let mut vv = VersionVector::new();
1058        vv.insert(1, 10);
1059        vv.insert(2, 20);
1060        vv.insert(3, 30);
1061
1062        // Encode VersionVector
1063        let encoded = vv.encode();
1064
1065        // Decode to ImVersionVector
1066        let decoded_im_vv = ImVersionVector::decode(&encoded).unwrap();
1067
1068        // Convert VersionVector to ImVersionVector for comparison
1069        let im_vv = vv.to_im_vv();
1070
1071        // Compare the original ImVersionVector with the decoded one
1072        assert_eq!(im_vv, decoded_im_vv);
1073
1074        // Convert back to VersionVector and compare
1075        let decoded_vv = VersionVector::from_im_vv(&decoded_im_vv);
1076        assert_eq!(vv, decoded_vv);
1077    }
1078}