1use core::fmt::{Debug, Formatter, Result as FmtResult};
2use core::ops::{Add, Range as StdRange, RangeBounds, Sub};
3
4use crate::Length;
5
6#[derive(Clone, Copy, PartialEq, Eq, Hash)]
7pub(crate) struct Range<T> {
8 pub start: T,
9 pub end: T,
10}
11
12impl<T: Debug> Debug for Range<T> {
13 fn fmt(&self, f: &mut Formatter) -> FmtResult {
14 write!(f, "{:?}..{:?}", self.start, self.end)
15 }
16}
17
18impl<T> From<StdRange<T>> for Range<T> {
19 #[inline]
20 fn from(range: StdRange<T>) -> Self {
21 Range { start: range.start, end: range.end }
22 }
23}
24
25impl<T> From<Range<T>> for StdRange<T> {
26 #[inline]
27 fn from(range: Range<T>) -> Self {
28 StdRange { start: range.start, end: range.end }
29 }
30}
31
32impl<T: Sub<T, Output = T> + Copy> Sub<T> for Range<T> {
33 type Output = Range<T>;
34
35 #[inline]
36 fn sub(self, value: T) -> Self::Output {
37 Range { start: self.start - value, end: self.end - value }
38 }
39}
40
41impl<T: Add<T, Output = T> + Copy> Add<T> for Range<T> {
42 type Output = Range<T>;
43
44 #[inline]
45 fn add(self, value: T) -> Self::Output {
46 Range { start: self.start + value, end: self.end + value }
47 }
48}
49
50impl<T> Range<T> {
51 #[inline]
52 pub fn len(&self) -> T
53 where
54 T: Sub<T, Output = T> + Copy,
55 {
56 self.end - self.start
57 }
58}
59
60pub(crate) trait RangeExt<T> {
61 fn contains_range(&self, range: Range<T>) -> bool;
62}
63
64impl<T: Ord> RangeExt<T> for StdRange<T> {
65 #[inline]
66 fn contains_range(&self, other: Range<T>) -> bool {
67 self.start <= other.start && self.end >= other.end
68 }
69}
70
71#[inline]
73pub(crate) fn get_two_mut<T>(
74 slice: &mut [T],
75 first_idx: usize,
76 second_idx: usize,
77) -> (&mut T, &mut T) {
78 debug_assert!(first_idx != second_idx);
79
80 if first_idx < second_idx {
81 debug_assert!(second_idx < slice.len());
82 let split_at = first_idx + 1;
83 let (first, second) = slice.split_at_mut(split_at);
84 (&mut first[first_idx], &mut second[second_idx - split_at])
85 } else {
86 debug_assert!(first_idx < slice.len());
87 let split_at = second_idx + 1;
88 let (first, second) = slice.split_at_mut(split_at);
89 (&mut second[first_idx - split_at], &mut first[second_idx])
90 }
91}
92
93#[inline]
95pub(crate) fn insert_in_slice<T>(slice: &mut [T], elem: T, at_offset: usize) {
96 debug_assert!(at_offset < slice.len());
97 slice[at_offset..].rotate_right(1);
98 slice[at_offset] = elem;
99}
100
101#[inline(always)]
103pub(crate) fn range_bounds_to_start_end<R>(
104 range: R,
105 lo: Length,
106 hi: Length,
107) -> (Length, Length)
108where
109 R: RangeBounds<Length>,
110{
111 use core::ops::Bound;
112
113 let start = match range.start_bound() {
114 Bound::Included(&n) => n,
115 Bound::Excluded(&n) => n + 1,
116 Bound::Unbounded => lo,
117 };
118
119 let end = match range.end_bound() {
120 Bound::Included(&n) => n + 1,
121 Bound::Excluded(&n) => n,
122 Bound::Unbounded => hi,
123 };
124
125 (start, end)
126}
127
128pub mod panic_messages {
129 use crate::Length;
130
131 #[track_caller]
132 #[cold]
133 #[inline(never)]
134 pub(crate) fn offset_out_of_bounds(offset: Length, len: Length) -> ! {
135 debug_assert!(offset > len);
136 panic!(
137 "offset out of bounds: the offset is {offset} but the length is \
138 {len}"
139 );
140 }
141
142 #[track_caller]
143 #[cold]
144 #[inline(never)]
145 pub(crate) fn replica_id_equal_to_forked() -> ! {
146 panic!(
147 "invalid ReplicaId: must not be equal to the one of the forked \
148 Replica, consider cloning instead"
149 );
150 }
151
152 #[track_caller]
153 #[cold]
154 #[inline(never)]
155 pub(crate) fn replica_id_is_zero() -> ! {
156 panic!("invalid ReplicaId: must not be zero");
157 }
158
159 #[track_caller]
160 #[cold]
161 #[inline(never)]
162 pub(crate) fn start_greater_than_end(start: Length, end: Length) -> ! {
163 debug_assert!(start > end);
164 panic!(
165 "offset range's start is greater than its end: the start is \
166 {start} but the end is {end}"
167 );
168 }
169}