1#![doc(hidden)]
2
3use core::fmt::Display;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct ByteRange(
10 pub usize,
12 pub usize,
14);
15
16impl ByteRange {
17 pub fn new(from: usize, to: usize) -> Self {
20 ByteRange(from.min(to), to.max(from))
21 }
22
23 pub fn new_unchecked(from: usize, to: usize) -> Self {
25 ByteRange(from, to)
26 }
27
28 pub fn aligned(&self, alignment: usize) -> Self {
30 let modulo = self.0 % alignment;
31 if modulo == 0 {
32 return *self;
33 }
34 self.offset(alignment - modulo)
35 }
36
37 pub fn cap_end(&self, position: usize) -> Self {
39 ByteRange(self.0, position.min(self.1))
40 }
41
42 pub fn cap_size(&self, size: usize) -> Self {
44 if self.len() < size {
45 return *self;
46 }
47 ByteRange(self.0, self.0 + size)
48 }
49
50 pub fn offset(&self, offset: usize) -> Self {
52 ByteRange(self.0 + offset, self.1 + offset)
53 }
54
55 pub fn offset_signed(&self, offset: isize) -> Self {
57 ByteRange(
58 ((self.0 as isize).wrapping_add(offset)) as usize,
59 ((self.1 as isize).wrapping_add(offset)) as usize,
60 )
61 }
62
63 pub fn len(&self) -> usize {
65 self.1 - self.0
66 }
67
68 pub fn is_empty(&self) -> bool {
70 self.0 == self.1
71 }
72
73 pub fn contains(&self, other: Self) -> bool {
75 self.0 <= other.0 && other.1 <= self.1
76 }
77
78 pub fn difference_unchecked(&self, other: Self) -> (Self, Self) {
85 (ByteRange(self.0, other.0), ByteRange(other.1, self.1))
86 }
87
88 pub fn merge_unchecked(&self, other: Self) -> Self {
91 ByteRange(self.0.min(other.0), self.1.max(other.1))
92 }
93
94 pub fn merge_in_unchecked(&mut self, other: Self) {
97 self.0 = self.0.min(other.0);
98 self.1 = self.1.max(other.1);
99 }
100}
101
102impl Display for ByteRange {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 write!(f, "[{:x}, {:x})", self.0, self.1)
105 }
106}
107
108#[cfg(test)]
109mod test {
110 use super::*;
111
112 #[test]
113 fn byterange_merging_works() {
114 let a = ByteRange::new_unchecked(0, 10);
115 let b = ByteRange::new_unchecked(10, 20);
116
117 let added_seq = a.merge_unchecked(b);
118 assert_eq!(added_seq.0, 0);
119 assert_eq!(added_seq.1, 20);
120
121 let added_seq_rev = b.merge_unchecked(a);
122 assert_eq!(added_seq_rev.0, 0);
123 assert_eq!(added_seq_rev.1, 20);
124 }
125
126 #[test]
127 fn byterange_difference_works() {
128 let larger = ByteRange::new_unchecked(0, 500);
129
130 let left_aligned = ByteRange::new_unchecked(0, 10);
131 let test_left = larger.difference_unchecked(left_aligned);
132 assert_eq!(test_left.0 .0, 0);
133 assert_eq!(test_left.0 .1, 0);
134 assert_eq!(test_left.1 .0, 10);
135 assert_eq!(test_left.1 .1, 500);
136
137 let contained = ByteRange::new_unchecked(300, 400);
138 let test_contained = larger.difference_unchecked(contained);
139 assert_eq!(test_contained.0 .0, 0);
140 assert_eq!(test_contained.0 .1, 300);
141 assert_eq!(test_contained.1 .0, 400);
142 assert_eq!(test_contained.1 .1, 500);
143
144 let right_aligned = ByteRange::new_unchecked(450, 500);
145 let test_right = larger.difference_unchecked(right_aligned);
146 assert_eq!(test_right.0 .0, 0);
147 assert_eq!(test_right.0 .1, 450);
148 assert_eq!(test_right.1 .0, 500);
149 assert_eq!(test_right.1 .1, 500);
150 }
151}