1use std::borrow::Cow;
14use std::result;
15use std::io::{self, Cursor, Write, Seek, SeekFrom};
16use byteorder::{WriteBytesExt, LittleEndian};
17use std::collections::HashMap;
18use crate::crc::vorbis_crc32_update;
19
20
21type IoResult<T> = result::Result<T, io::Error>;
26
27pub struct PacketWriter<'writer, T :io::Write> {
34 wtr :T,
35
36 page_vals :HashMap<u32, CurrentPageValues<'writer>>,
37}
38
39struct CurrentPageValues<'writer> {
40 first_page :bool,
42 sequence_num :u32,
45
46 segment_cnt :u8,
48 cur_pg_lacing :[u8; 255],
49 cur_pg_data :Vec<(Cow<'writer, [u8]>, u64)>,
51
52 pck_this_overflow_idx :Option<usize>,
62
63 pck_last_overflow_idx :Option<usize>,
72}
73
74#[derive(PartialEq)]
83#[derive(Clone, Copy)]
84pub enum PacketWriteEndInfo {
85 NormalPacket,
87 EndPage,
89 EndStream,
91}
92
93impl <'writer, T :io::Write> PacketWriter<'writer, T> {
94 pub fn new(wtr :T) -> Self {
95 return PacketWriter {
96 wtr,
97 page_vals : HashMap::new(),
98 };
99 }
100 pub fn into_inner(self) -> T {
101 self.wtr
102 }
103 pub fn inner(&self) -> &T {
109 &self.wtr
110 }
111 pub fn inner_mut(&mut self) -> &mut T {
117 &mut self.wtr
118 }
119 pub fn write_packet<P: Into<Cow<'writer, [u8]>>>(&mut self, pck_cont :P,
123 serial :u32,
124 inf :PacketWriteEndInfo,
125 absgp :u64) -> IoResult<()> {
132 let is_end_stream :bool = inf == PacketWriteEndInfo::EndStream;
133 let pg = self.page_vals.entry(serial).or_insert(
134 CurrentPageValues {
135 first_page : true,
136 sequence_num : 0,
137 segment_cnt : 0,
138 cur_pg_lacing :[0; 255],
139 cur_pg_data :Vec::with_capacity(255),
140 pck_this_overflow_idx : None,
141 pck_last_overflow_idx : None,
142 }
143 );
144
145 let pck_cont = pck_cont.into();
146 let cont_len = pck_cont.len();
147 pg.cur_pg_data.push((pck_cont, absgp));
148
149 let last_data_segment_size = (cont_len % 255) as u8;
150 let needed_segments :usize = (cont_len / 255) + 1;
151 let mut segment_in_page_i :u8 = pg.segment_cnt;
152 let mut at_page_end :bool = false;
153 for segment_i in 0 .. needed_segments {
154 at_page_end = false;
155 if segment_i + 1 < needed_segments {
156 pg.cur_pg_lacing[segment_in_page_i as usize] = 255;
158 } else {
159 pg.cur_pg_lacing[segment_in_page_i as usize] = last_data_segment_size;
162 }
163 pg.segment_cnt = segment_in_page_i + 1;
164 segment_in_page_i = (segment_in_page_i + 1) % 255;
165 if segment_in_page_i == 0 {
166 if segment_i + 1 < needed_segments {
167 pg.pck_this_overflow_idx = Some((segment_i + 1) * 255);
169 tri!(PacketWriter::write_page(&mut self.wtr, serial, pg,
170 false));
171 } else {
172 tri!(PacketWriter::write_page(&mut self.wtr,
175 serial, pg, is_end_stream));
176 pg.pck_this_overflow_idx = None;
180 pg.pck_last_overflow_idx = None;
182 }
183 at_page_end = true;
184 }
185 }
186 if (inf != PacketWriteEndInfo::NormalPacket) && !at_page_end {
187 tri!(PacketWriter::write_page(&mut self.wtr, serial, pg,
189 is_end_stream));
190
191 pg.pck_last_overflow_idx = None;
192
193 }
197 Ok(())
199 }
200 fn write_page(wtr :&mut T, serial :u32, pg :&mut CurrentPageValues,
201 last_page :bool) -> IoResult<()> {
202 {
203 let mut hdr_cur = Cursor::new(Vec::with_capacity(27));
205 tri!(hdr_cur.write_all(&[0x4f, 0x67, 0x67, 0x53, 0x00]));
206 let mut flags :u8 = 0;
207 if pg.pck_last_overflow_idx.is_some() { flags |= 0x01; }
208 if pg.first_page { flags |= 0x02; }
209 if last_page { flags |= 0x04; }
210
211 tri!(hdr_cur.write_u8(flags));
212
213 let pck_data = &pg.cur_pg_data;
214
215 let mut last_finishing_pck_absgp = (-1i64) as u64;
216 for (idx, &(_, absgp)) in pck_data.iter().enumerate() {
217 if !(idx + 1 == pck_data.len() &&
218 pg.pck_this_overflow_idx.is_some()) {
219 last_finishing_pck_absgp = absgp;
220 }
221 }
222
223 tri!(hdr_cur.write_u64::<LittleEndian>(last_finishing_pck_absgp));
224 tri!(hdr_cur.write_u32::<LittleEndian>(serial));
225 tri!(hdr_cur.write_u32::<LittleEndian>(pg.sequence_num));
226
227 tri!(hdr_cur.write_u32::<LittleEndian>(0));
229
230 tri!(hdr_cur.write_u8(pg.segment_cnt));
231
232 let mut hash_calculated :u32;
233
234 let pg_lacing = &pg.cur_pg_lacing[0 .. pg.segment_cnt as usize];
235
236
237 hash_calculated = vorbis_crc32_update(0, hdr_cur.get_ref());
238 hash_calculated = vorbis_crc32_update(hash_calculated, pg_lacing);
239
240 for (idx, (pck, _)) in pck_data.iter().enumerate() {
241 let mut start :usize = 0;
242 if idx == 0 { if let Some(idx) = pg.pck_last_overflow_idx {
243 start = idx;
244 }}
245 let mut end :usize = pck.len();
246 if idx + 1 == pck_data.len() {
247 if let Some(idx) = pg.pck_this_overflow_idx {
248 end = idx;
249 }
250 }
251 hash_calculated = vorbis_crc32_update(hash_calculated,
252 &pck[start .. end]);
253 }
254
255 tri!(hdr_cur.seek(SeekFrom::Start(22)));
260 tri!(hdr_cur.write_u32::<LittleEndian>(hash_calculated));
261
262 tri!(wtr.write_all(hdr_cur.get_ref()));
264 tri!(wtr.write_all(pg_lacing));
265 for (idx, (pck, _)) in pck_data.iter().enumerate() {
266 let mut start :usize = 0;
267 if idx == 0 { if let Some(idx) = pg.pck_last_overflow_idx {
268 start = idx;
269 }}
270 let mut end :usize = pck.len();
271 if idx + 1 == pck_data.len() {
272 if let Some(idx) = pg.pck_this_overflow_idx {
273 end = idx;
274 }
275 }
276 tri!(wtr.write_all(&pck[start .. end]));
277 }
278 }
279
280 pg.first_page = false;
282 pg.sequence_num += 1;
283
284 pg.segment_cnt = 0;
285 if pg.pck_this_overflow_idx.is_some() {
289 let d = pg.cur_pg_data.pop().unwrap();
290 pg.cur_pg_data.clear();
291 pg.cur_pg_data.push(d);
292 } else {
293 pg.cur_pg_data.clear();
294 }
295
296 pg.pck_last_overflow_idx = pg.pck_this_overflow_idx;
297 pg.pck_this_overflow_idx = None;
298
299 return Ok(());
300 }
301}
302
303impl<T :io::Seek + io::Write> PacketWriter<'_, T> {
304 pub fn get_current_offs(&mut self) -> Result<u64, io::Error> {
305 self.wtr.stream_position()
306 }
307}
308
309#[test]
312fn test_recapture() {
313 use std::io::Write;
317 use super::PacketReader;
318 let mut c = Cursor::new(Vec::new());
319 let test_arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
320 let test_arr_2 = [2, 4, 8, 16, 32, 64, 128, 127, 126, 125, 124];
321 let test_arr_3 = [3, 5, 9, 17, 33, 65, 129, 129, 127, 126, 125];
322 {
323 let np = PacketWriteEndInfo::NormalPacket;
324 let ep = PacketWriteEndInfo::EndPage;
325 {
326 let mut w = PacketWriter::new(&mut c);
327 w.write_packet(&test_arr[..], 0xdeadb33f, ep, 0).unwrap();
328
329 w.wtr.write_all(&[0; 38]).unwrap();
331
332 w.write_packet(&test_arr_2[..], 0xdeadb33f, np, 1).unwrap();
333 w.write_packet(&test_arr_3[..], 0xdeadb33f, ep, 2).unwrap();
334 }
335 }
336 assert_eq!(c.seek(SeekFrom::Start(0)).unwrap(), 0);
338 {
339 let mut r = PacketReader::new(c);
340 let p1 = r.read_packet().unwrap().unwrap();
341 assert_eq!(test_arr, *p1.data);
342 let p2 = r.read_packet().unwrap().unwrap();
343 assert_eq!(test_arr_2, *p2.data);
344 let p3 = r.read_packet().unwrap().unwrap();
345 assert_eq!(test_arr_3, *p3.data);
346 }
347}