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#[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#[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 pub retreat: IdSpanVector,
309 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 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 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 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 pub fn iter_between<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = IdSpan> + 'a {
587 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 #[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 #[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 #[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#[tracing::instrument(skip(dag))]
863pub fn shrink_frontiers(last_ids: &Frontiers, dag: &AppDag) -> Result<Frontiers, ID> {
864 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 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 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 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
982pub 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 let encoded = vv.encode();
1064
1065 let decoded_im_vv = ImVersionVector::decode(&encoded).unwrap();
1067
1068 let im_vv = vv.to_im_vv();
1070
1071 assert_eq!(im_vv, decoded_im_vv);
1073
1074 let decoded_vv = VersionVector::from_im_vv(&decoded_im_vv);
1076 assert_eq!(vv, decoded_vv);
1077 }
1078}