1pub mod buffer;
2pub mod storage;
3
4use std::ops;
5
6pub use buffer::Buffer;
7pub use storage::SharedStorage;
8
9fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
11 if start > len {
12 panic!("range start index {start} out of range for slice of length {len}",)
13 }
14
15 if end > len {
16 panic!("range end index {end} out of range for slice of length {len}",)
17 }
18
19 if start > end {
20 panic!("slice index starts at {start} but ends at {end}",)
21 }
22
23 panic!("range end index {end} out of range for slice of length {len}",)
26}
27
28#[must_use]
29pub fn check_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
30where
31 R: ops::RangeBounds<usize>,
32{
33 let len = bounds.end;
34 let end = match range.end_bound() {
35 ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len),
36 ops::Bound::Included(&end) => end + 1,
38
39 ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len),
40 ops::Bound::Excluded(&end) => end,
41 ops::Bound::Unbounded => len,
42 };
43
44 let start = match range.start_bound() {
45 ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len),
46 ops::Bound::Excluded(&start) => start + 1,
48
49 ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len),
50 ops::Bound::Included(&start) => start,
51
52 ops::Bound::Unbounded => 0,
53 };
54
55 ops::Range { start, end }
56}
57
58#[must_use]
59pub fn decode_range_unchecked<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
60where
61 R: ops::RangeBounds<usize>,
62{
63 let len = bounds.end;
64 let end = match range.end_bound() {
65 ops::Bound::Included(&end) => end + 1,
66 ops::Bound::Excluded(&end) => end,
67 ops::Bound::Unbounded => len,
68 };
69
70 let start = match range.start_bound() {
71 ops::Bound::Excluded(&start) => start + 1,
72 ops::Bound::Included(&start) => start,
73 ops::Bound::Unbounded => 0,
74 };
75
76 ops::Range { start, end }
77}