1use bytes::Bytes;
2
3pub struct ByteChunks<'a, T: 'a> {
4 v: &'a [T],
5 chunk_byte_size: usize,
6}
7
8pub trait SizeInBytes {
9 fn bytes_size(&self) -> usize;
10}
11
12impl SizeInBytes for String {
13 fn bytes_size(&self) -> usize {
14 let bytes: Bytes = self.to_owned().into();
15 bytes.len()
16 }
17}
18
19impl<'a> SizeInBytes for &'a str {
20 fn bytes_size(&self) -> usize {
21 let bytes: Bytes = self.to_string().into();
22 bytes.len()
23 }
24}
25
26impl<'a, T: 'a> ByteChunks<'a, T>
27where
28 T: SizeInBytes,
29{
30 pub fn new(slice: &'a [T], size: usize) -> Self {
31 Self {
32 v: slice,
33 chunk_byte_size: size,
34 }
35 }
36
37 fn next_split_index(&mut self) -> usize {
38 let mut byte_count = 0;
39 let mut index = 0;
40 loop {
41 let next = self.v.get(index);
42 match next {
43 Some(d) => {
44 let size_of_next = d.bytes_size();
45 if size_of_next > self.chunk_byte_size {
46 panic!("Chunk is larger than {} bytes", self.chunk_byte_size);
47 } else if byte_count + size_of_next > self.chunk_byte_size {
48 break;
49 } else {
50 byte_count += size_of_next;
51 index += 1;
52 }
53 }
54 None => break,
55 }
56 }
57 index
58 }
59}
60
61impl<'a, T> Iterator for ByteChunks<'a, T>
62where
63 T: SizeInBytes,
64{
65 type Item = &'a [T];
66
67 fn next(&mut self) -> Option<&'a [T]> {
68 if self.v.is_empty() {
69 None
70 } else {
71 let chunksz = self.next_split_index();
72 let (fst, snd) = self.v.split_at(chunksz);
73 self.v = snd;
74 Some(fst)
75 }
76 }
77}
78
79pub trait ByteChunked<'a, T> {
80 fn byte_chunks(&self, chunk_byte_size: usize) -> ByteChunks<'_, T>;
81}
82
83pub trait SafeByteChunkedMut<'a, T> {
84 fn byte_chunks_safe_mut(&mut self, chunk_byte_size: usize) -> ByteChunks<'_, T>;
85}
86
87pub trait SafeByteChunked<'a, T> {
88 fn byte_chunks_safe(&mut self, chunk_byte_size: usize) -> ByteChunks<'_, T>;
89}
90
91impl<T> ByteChunked<'_, T> for [T]
92where
93 T: SizeInBytes,
94{
95 fn byte_chunks(&self, chunk_byte_size: usize) -> ByteChunks<'_, T> {
96 ByteChunks::new(self, chunk_byte_size)
97 }
98}
99
100impl<T> ByteChunked<'_, T> for Vec<T>
101where
102 T: SizeInBytes,
103{
104 fn byte_chunks(&self, chunk_byte_size: usize) -> ByteChunks<'_, T> {
105 ByteChunks::new(self.as_slice(), chunk_byte_size)
106 }
107}
108
109impl<T> SafeByteChunkedMut<'_, T> for Vec<T>
110where
111 T: SizeInBytes,
112{
113 fn byte_chunks_safe_mut(&mut self, chunk_byte_size: usize) -> ByteChunks<'_, T> {
114 self.retain(|x| x.bytes_size() <= chunk_byte_size);
115 ByteChunks::new(self.as_slice(), chunk_byte_size)
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::{ByteChunked, SafeByteChunkedMut};
122 use std::mem::size_of_val;
123
124 #[test]
125 fn test_next_split_index() {
126 let data: Vec<&str> = vec!["Hello", "There", "Best", "Worl", "D", "A"];
127 let mut chunked = data.as_slice().byte_chunks(10);
128 let next_index = chunked.next_split_index();
129
130 assert_eq!(2, next_index);
131 }
132
133 #[test]
134 fn size_of_tests() {
135 let string_ref = "test";
136 assert_eq!(size_of_val(string_ref), 4);
137 }
138
139 #[test]
140 fn creates_chunks_static_str() {
141 let data: Vec<&str> = vec!["Hello", "There", "Best", "Worl", "D", "A"];
142 let mut chunk_iter = data.byte_chunks(10);
143 if let Some(next) = chunk_iter.next() {
144 println!("{:?}", next);
145 assert_eq!(2, next.len());
146 }
147
148 if let Some(next) = chunk_iter.next() {
149 println!("{:?}", next);
150 assert_eq!(4, next.len());
151 }
152
153 let next = chunk_iter.next();
154 assert_eq!(None, next);
155 }
156
157 #[test]
158 fn creates_chunks_string() {
159 let data: Vec<String> = (vec!["Hello", "There", "Best", "Worl", "D", "A"])
160 .iter()
161 .map(|&x| String::from(x))
162 .collect();
163
164 let mut chunk_iter = data.byte_chunks(10);
165
166 if let Some(next) = chunk_iter.next() {
167 println!("{:?}", next);
168 assert_eq!(2, next.len());
169 }
170
171 if let Some(next) = chunk_iter.next() {
172 println!("{:?}", next);
173 assert_eq!(4, next.len());
174 }
175 let next = chunk_iter.next();
176 assert_eq!(None, next);
177 }
178
179 #[test]
180 fn empty_vec_returns_none() {
181 let data: Vec<String> = Vec::new();
182
183 let mut chunk_iter = data.byte_chunks(10);
184
185 let next = chunk_iter.next();
186 assert_eq!(None, next);
187 }
188
189 #[test]
191 fn special_chars_are_sized_with_string() {
192 let data: Vec<String> = vec!["ラウ", "トは", "難し", "いで", "す!"]
193 .iter()
194 .map(|&x| String::from(x))
195 .collect();
196
197 let mut chunk_iter = data.byte_chunks(12);
198
199 if let Some(next) = chunk_iter.next() {
200 println!("{:?}", next);
201 assert_eq!(2, next.len());
202 }
203
204 if let Some(next) = chunk_iter.next() {
205 println!("{:?}", next);
206 assert_eq!(2, next.len());
207 }
208
209 if let Some(next) = chunk_iter.next() {
210 println!("{:?}", next);
211 assert_eq!(1, next.len());
212 }
213 let next = chunk_iter.next();
214 assert_eq!(None, next);
215 }
216
217 #[test]
218 fn special_chars_are_sized_with_static_string() {
219 let data = vec!["ラウ", "トは", "難し", "いで", "す!"];
220
221 let mut chunk_iter = data.byte_chunks(12);
222
223 if let Some(next) = chunk_iter.next() {
224 println!("{:?}", next);
225 assert_eq!(2, next.len());
226 }
227
228 if let Some(next) = chunk_iter.next() {
229 println!("{:?}", next);
230 assert_eq!(2, next.len());
231 }
232
233 if let Some(next) = chunk_iter.next() {
234 println!("{:?}", next);
235 assert_eq!(1, next.len());
236 }
237 let next = chunk_iter.next();
238 assert_eq!(None, next);
239 }
240
241 #[test]
242 fn strings_that_are_too_large_are_skipped() {
243 let mut data: Vec<String> = vec!["Hello", "There"]
244 .iter()
245 .map(|&x| String::from(x))
246 .collect();
247 let mut chunk_iter = data.byte_chunks_safe_mut(3);
248
249 let next = chunk_iter.next();
250 assert_eq!(None, next);
251 }
252}