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