1use crate::value::{InMemFragment, PixelFragmentSequence, C};
3
4#[derive(Debug)]
38pub struct Fragments {
39 fragments: Vec<InMemFragment>,
40}
41
42impl Fragments {
43 pub fn new(data: Vec<u8>, fragment_size: u32) -> Self {
44 let fragment_size: u32 = if fragment_size == 0 {
45 data.len() as u32
46 } else {
47 fragment_size
48 };
49
50 let fragment_size = if fragment_size % 2 == 0 {
51 fragment_size
52 } else {
53 fragment_size + 1
54 };
55
56 let number_of_fragments = (data.len() as f32 / fragment_size as f32).ceil() as u32;
57
58 let mut data = data;
61 let encapsulated_size = (fragment_size * number_of_fragments) as usize;
62 if encapsulated_size > data.len() {
63 data.resize(encapsulated_size, 0);
64 }
65
66 let fragments = data
67 .chunks_exact(fragment_size as usize)
68 .map(|fragment| fragment.to_vec())
69 .collect::<Vec<InMemFragment>>();
70
71 Fragments { fragments }
72 }
73
74 pub fn is_empty(&self) -> bool {
75 self.fragments.len() == 0
76 }
77
78 pub fn is_multiframe(&self) -> bool {
79 self.fragments.len() > 1
80 }
81
82 pub fn len(&self) -> u32 {
83 self.fragments
84 .iter()
85 .fold(0u32, |acc, fragment| acc + fragment.len() as u32 + 8u32)
86 }
87}
88
89impl From<Vec<Fragments>> for PixelFragmentSequence<InMemFragment> {
90 fn from(value: Vec<Fragments>) -> Self {
91 if value.is_empty() {
92 return PixelFragmentSequence {
94 offset_table: C::new(),
95 fragments: C::new(),
96 };
97 }
98
99 let mut offset_table = C::with_capacity(value.len() + 1);
100 offset_table.push(0u32);
101 let mut current_offset = 0u32;
102
103 let mut fragments = Vec::new();
104 let is_multiframe = value.len() > 1;
105 let last_frame = value.len() - 1;
106
107 for (index, mut frame) in value.into_iter().enumerate() {
108 if frame.is_multiframe() && is_multiframe {
109 panic!("More than 1 fragment per frame is invalid for multi frame pixel data");
110 }
111
112 if index < last_frame {
113 let offset = frame.len();
114 offset_table.push(current_offset + offset);
115 current_offset += offset;
116 }
117
118 fragments.append(&mut frame.fragments);
119 }
120
121 PixelFragmentSequence {
122 offset_table,
123 fragments: C::from_vec(fragments),
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use crate::value::fragments::Fragments;
131 use crate::value::{InMemFragment, PixelFragmentSequence};
132
133 #[test]
134 fn test_fragment_frame() {
135 let fragment = Fragments::new(vec![150, 164, 200], 0);
136 assert_eq!(fragment.fragments.len(), 1, "1 fragment should be present");
137 assert_eq!(
138 fragment.fragments[0].len(),
139 4,
140 "The fragment size should be 4"
141 );
142 assert_eq!(
143 fragment.fragments[0],
144 vec![150, 164, 200, 0],
145 "The data should be 0 padded"
146 );
147
148 let fragment = Fragments::new(vec![150, 164, 200, 222], 4);
149 assert_eq!(fragment.fragments.len(), 1, "1 fragment should be present");
150 assert_eq!(
151 fragment.fragments[0].len(),
152 4,
153 "The fragment size should be 4"
154 );
155 assert_eq!(
156 fragment.fragments[0],
157 vec![150, 164, 200, 222],
158 "The data should be what was sent"
159 );
160
161 let fragment = Fragments::new(vec![150, 164, 200, 222], 2);
162 assert_eq!(fragment.fragments.len(), 2, "2 fragments should be present");
163 assert_eq!(fragment.fragments[0].len(), 2);
164 assert_eq!(fragment.fragments[1].len(), 2);
165 assert_eq!(fragment.fragments[0], vec![150, 164]);
166 assert_eq!(fragment.fragments[1], vec![200, 222]);
167
168 let fragment = Fragments::new(vec![150, 164, 200], 1);
169 assert_eq!(
170 fragment.fragments.len(),
171 2,
172 "2 fragments should be present as fragment_size < 2"
173 );
174 assert_eq!(fragment.fragments[0].len(), 2);
175 assert_eq!(fragment.fragments[0], vec![150, 164]);
176 assert_eq!(fragment.fragments[1].len(), 2);
177 assert_eq!(fragment.fragments[1], vec![200, 0]);
178
179 let fragment = Fragments::new(vec![150, 164, 200, 222], 1);
180 assert_eq!(
181 fragment.fragments.len(),
182 2,
183 "2 fragments should be present as fragment_size < 2"
184 );
185 assert_eq!(fragment.fragments[0].len(), 2);
186 assert_eq!(fragment.fragments[0], vec![150, 164]);
187 assert_eq!(fragment.fragments[1].len(), 2);
188 assert_eq!(fragment.fragments[1], vec![200, 222]);
189 }
190
191 #[test]
192 fn test_bot_single_fragment_generation() {
193 let data = vec![Fragments::new(vec![0u8; 2], 2)];
194 let fragment_sequence: PixelFragmentSequence<InMemFragment> = data.into();
195 assert_eq!(fragment_sequence.offset_table.len(), 1);
196 assert_eq!(fragment_sequence.offset_table[0], 0);
197 }
198
199 #[test]
200 fn test_bot_multi_fragments_generation() {
201 let data = vec![Fragments::new(vec![0u8; 4], 2)];
202 let fragment_sequence: PixelFragmentSequence<InMemFragment> = data.into();
203 assert_eq!(fragment_sequence.offset_table.len(), 1);
204 assert_eq!(fragment_sequence.offset_table[0], 0);
205 }
206
207 #[test]
208 fn test_bot_multi_frame_generation() {
209 let data = vec![
210 Fragments::new(vec![0u8; 4], 0),
211 Fragments::new(vec![1u8; 6], 0),
212 ];
213 let fragment_sequence: PixelFragmentSequence<InMemFragment> = data.into();
214 assert_eq!(fragment_sequence.offset_table.len(), 2);
215 assert_eq!(fragment_sequence.offset_table[0], 0);
216 assert_eq!(fragment_sequence.offset_table[1], 12); }
218}