1use std::io::{BufReader, Cursor, Read, Seek};
4
5use smdiff_common::SectionHeader;
6use smdiff_reader::{read_ops_no_comp, read_section_header, Op};
7
8use crate::apply_no_sec_comp;
9
10pub struct SectionIterator<R>{
12 source: BufReader<R>,
13 done:bool,
14 win_data: Vec<u8>,
15 ops: Vec<Op>,
16}
17impl<R: Read+Seek> SectionIterator<R>{
18 pub fn new(patch: R) -> Self {
19 Self {
20 source:BufReader::new(patch),
21 done:false,
22 win_data: Vec::new(),
23 ops: Vec::new(),
24 }
25 }
26 pub fn next_borrowed(&mut self) -> Option<std::io::Result<(&[Op],SectionHeader)>>{
30 let mut header = match self.read_header()?{
31 Ok(h) => h,
32 Err(e) => {
33 return Some(Err(e));
34 }
35 };
36 self.ops.clear();
37 if let Err(e) = self.read_ops(&mut header){
38 return Some(Err(e));
39 }
40 Some(Ok((&self.ops,header)))
41 }
42 fn next_owned(&mut self) -> Option<std::io::Result<(Vec<Op>,SectionHeader)>>{
44 let mut header = match self.read_header()?{
45 Ok(h) => h,
46 Err(e) => {
47 return Some(Err(e));
48 }
49 };
50 self.ops.clear();
51 if let Err(e) = self.read_ops(&mut header){
52 return Some(Err(e));
53 }
54 Some(Ok((std::mem::take(&mut self.ops),header)))
55 }
56 fn read_header(&mut self) -> Option<std::io::Result<SectionHeader>>{
57 if self.done{
58 return None;
59 }
60 match read_section_header(&mut self.source){
61 Ok(h) => Some(Ok(h)),
62 Err(e) => {
63 return Some(Err(e));
64 }
65 }
66 }
67 fn read_ops(&mut self,header:&mut SectionHeader) -> std::io::Result<()>{
68 self.win_data.clear();
69 self.ops.clear();
70 if header.compression_algo == 1 {
71 let mut crsr = Cursor::new(&mut self.win_data);
72 apply_no_sec_comp::<_,R,_>(&mut self.source, None, &mut crsr)?;
73 crsr.rewind()?;
74 read_ops_no_comp(&mut crsr, header,&mut self.ops)?;
75 }else if header.compression_algo == 2 {
76 let mut zstd = ruzstd::StreamingDecoder::new(&mut self.source).unwrap();
77 read_ops_no_comp(&mut zstd, header,&mut self.ops)?;
78 }else if header.compression_algo == 3 {
79 let mut brot = brotlic::DecompressorReader::new(&mut self.source);
80 read_ops_no_comp(&mut brot, header,&mut self.ops)?;
81 let _ = brot.into_inner()?;
82 }else{
83 read_ops_no_comp(&mut self.source, header,&mut self.ops)?;
84 }
85 if !header.more_sections{
86 self.done = true;
87 }
88 Ok(())
89 }
90 pub fn into_inner(self) -> R {
91 self.source.into_inner()
92 }
93}
94
95impl<R: Read+Seek> Iterator for SectionIterator<R> {
96 type Item = std::io::Result<(Vec<Op>, SectionHeader)>;
97
98 fn next(&mut self) -> Option<Self::Item> {
99 self.next_owned()
100 }
101}