zerodds_dcps/
sample_bytes.rs1use alloc::sync::Arc;
28use alloc::vec::Vec;
29use core::ops::Range;
30
31#[derive(Debug, Clone)]
36pub struct SampleBytes {
37 data: Arc<[u8]>,
39 range: Range<usize>,
41}
42
43impl SampleBytes {
44 #[must_use]
48 pub fn from_vec(v: Vec<u8>) -> Self {
49 let len = v.len();
50 Self {
51 data: Arc::from(v.into_boxed_slice()),
52 range: 0..len,
53 }
54 }
55
56 #[must_use]
59 pub fn from_arc(data: Arc<[u8]>) -> Self {
60 let len = data.len();
61 Self {
62 data,
63 range: 0..len,
64 }
65 }
66
67 #[must_use]
72 pub fn from_arc_slice(data: Arc<[u8]>, range: Range<usize>) -> Self {
73 assert!(
74 range.end <= data.len() && range.start <= range.end,
75 "SampleBytes range out of bounds"
76 );
77 Self { data, range }
78 }
79
80 #[must_use]
86 pub fn slice(&self, sub: Range<usize>) -> Self {
87 assert!(sub.end <= self.len(), "SampleBytes::slice out of bounds");
88 let start = self.range.start + sub.start;
89 let end = self.range.start + sub.end;
90 Self {
91 data: Arc::clone(&self.data),
92 range: start..end,
93 }
94 }
95
96 #[must_use]
98 pub fn as_slice(&self) -> &[u8] {
99 &self.data[self.range.clone()]
100 }
101
102 #[must_use]
104 pub fn len(&self) -> usize {
105 self.range.end - self.range.start
106 }
107
108 #[must_use]
110 pub fn is_empty(&self) -> bool {
111 self.range.is_empty()
112 }
113
114 #[must_use]
117 pub fn to_vec(&self) -> Vec<u8> {
118 self.as_slice().to_vec()
119 }
120}
121
122impl AsRef<[u8]> for SampleBytes {
123 fn as_ref(&self) -> &[u8] {
124 self.as_slice()
125 }
126}
127
128impl core::ops::Deref for SampleBytes {
129 type Target = [u8];
130 fn deref(&self) -> &[u8] {
131 self.as_slice()
132 }
133}
134
135impl PartialEq for SampleBytes {
136 fn eq(&self, other: &Self) -> bool {
137 self.as_slice() == other.as_slice()
138 }
139}
140
141impl Eq for SampleBytes {}
142
143impl From<Vec<u8>> for SampleBytes {
144 fn from(v: Vec<u8>) -> Self {
145 Self::from_vec(v)
146 }
147}
148
149impl From<Arc<[u8]>> for SampleBytes {
150 fn from(a: Arc<[u8]>) -> Self {
151 Self::from_arc(a)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn from_vec_roundtrip() {
161 let s = SampleBytes::from_vec(alloc::vec![1, 2, 3, 4]);
162 assert_eq!(s.len(), 4);
163 assert_eq!(s.as_slice(), &[1, 2, 3, 4]);
164 assert_eq!(s.to_vec(), alloc::vec![1, 2, 3, 4]);
165 }
166
167 #[test]
168 fn from_arc_full_range() {
169 let arc: Arc<[u8]> = Arc::from(alloc::vec![10, 20, 30].into_boxed_slice());
170 let s = SampleBytes::from_arc(arc);
171 assert_eq!(s.as_slice(), &[10, 20, 30]);
172 }
173
174 #[test]
175 fn slice_is_zero_copy() {
176 let arc: Arc<[u8]> = Arc::from(alloc::vec![1, 2, 3, 4, 5].into_boxed_slice());
177 let s = SampleBytes::from_arc(arc);
178 let inner_ptr_before = s.as_slice().as_ptr() as usize;
179 let sub = s.slice(2..5);
180 let inner_ptr_after = sub.as_slice().as_ptr() as usize;
181 assert_eq!(inner_ptr_after - inner_ptr_before, 2);
183 assert_eq!(sub.as_slice(), &[3, 4, 5]);
184 }
185
186 #[test]
187 fn nested_slice_offsets_compose() {
188 let s = SampleBytes::from_vec(alloc::vec![0, 1, 2, 3, 4, 5, 6, 7]);
189 let s1 = s.slice(2..7); let s2 = s1.slice(1..4); assert_eq!(s2.as_slice(), &[3, 4, 5]);
192 }
193
194 #[test]
195 fn clone_is_refcount_bump() {
196 let s = SampleBytes::from_vec(alloc::vec![1, 2, 3]);
197 let p1 = s.as_slice().as_ptr();
198 let s2 = s.clone();
199 let p2 = s2.as_slice().as_ptr();
200 assert_eq!(p1, p2, "Clone must share backing storage");
201 }
202
203 #[test]
204 fn empty_after_full_strip() {
205 let s = SampleBytes::from_vec(alloc::vec![1, 2, 3]);
206 let empty = s.slice(3..3);
207 assert!(empty.is_empty());
208 }
209
210 #[test]
211 #[should_panic(expected = "out of bounds")]
212 fn slice_oob_panics() {
213 let s = SampleBytes::from_vec(alloc::vec![1, 2]);
214 let _ = s.slice(0..5);
215 }
216}