docufort/
content_reader.rs1use std::{io::{Read, Seek, SeekFrom, Write}, ops::RangeBounds};
6
7use crate::{core::{BlockState, BlockInputs, Block, Content}, read::read_magic_number, recovery::{try_read_block, BlockReadSummary}, FILE_HEADER_LEN, MAGIC_NUMBER, ReadWriteError, ECC_LEN};
8
9pub fn find_content<RW:Read+Write+Seek,B:BlockInputs,T:RangeBounds<u64>>(file: &mut RW, start_hint: Option<u64>,range:Option<T>) -> Result<Vec<(u64,Content)>, ReadWriteError> {
26 let mut content = Vec::new();
27 if let Some(s) = start_hint {
28 file.seek(SeekFrom::Start(s))?;
29 }else{
30 file.seek(SeekFrom::Start(FILE_HEADER_LEN as u64 + MAGIC_NUMBER.len() as u64 + ECC_LEN as u64))?;}
32
33 let range =range.map(|u|{
34 match (u.start_bound(),u.end_bound()){
35 (std::ops::Bound::Included(a), std::ops::Bound::Included(b)) => a.to_be_bytes()..=b.to_be_bytes(),
36 (std::ops::Bound::Included(a), std::ops::Bound::Excluded(b)) => a.to_be_bytes()..=(b-1).to_be_bytes(),
37 (std::ops::Bound::Included(a), std::ops::Bound::Unbounded) =>a.to_be_bytes()..=u64::MAX.to_be_bytes(),
38 (std::ops::Bound::Excluded(a), std::ops::Bound::Included(b)) => (a+1).to_be_bytes()..=b.to_be_bytes(),
39 (std::ops::Bound::Excluded(a), std::ops::Bound::Excluded(b)) => (a+1).to_be_bytes()..=(b-1).to_be_bytes(),
40 (std::ops::Bound::Excluded(a), std::ops::Bound::Unbounded) => (a+1).to_be_bytes()..=u64::MAX.to_be_bytes(),
41 (std::ops::Bound::Unbounded, std::ops::Bound::Included(b)) => 0u64.to_be_bytes()..=b.to_be_bytes(),
42 (std::ops::Bound::Unbounded, std::ops::Bound::Excluded(b)) => 0u64.to_be_bytes()..=(b-1).to_be_bytes(),
43 (std::ops::Bound::Unbounded, std::ops::Bound::Unbounded) => 0u64.to_be_bytes()..=u64::MAX.to_be_bytes(),
44 }
45 });
46
47 'outer: loop {
54 let bs = try_read_block::<_, B>(file, false,false)?;
55 match bs {
56 BlockState::Closed(BlockReadSummary { block, .. }) => {
57 match block {
58 Block::A { middle,start,.. } => {
59 let start_time = start.time_stamp();
60 let ts = u64::from_be_bytes(start_time);
61 if let Some(r) = range.as_ref() {
62 if r.contains(&start_time){
63 content.push((ts,middle))
64 }else {
65 match r.end_bound(){
66 std::ops::Bound::Included(x) if &start_time > x => break,
67 std::ops::Bound::Excluded(x) if &start_time >= x => break,
68 _ => (),
69 }
70 }
71 }else{
72 content.push((ts,middle))
73 }
74 },
75 Block::B { middle, .. } => {
76 for (s,m) in middle {
77 let start_time = s.time_stamp();
78 let ts = u64::from_be_bytes(start_time);
79 if let Some(r) = range.as_ref() {
80 if r.contains(&start_time){
81 content.push((ts,m))
82 }else {
83 match r.end_bound(){
84 std::ops::Bound::Included(x) if &start_time > x => break 'outer,
85 std::ops::Bound::Excluded(x) if &start_time >= x => break 'outer,
86 _ => (),
87 }
88 }
89 }else{
90 content.push((ts,m))
91 }
92 }
93 },
94 }
95 },
96 BlockState::OpenBBlock { content:middle, .. } => {
97 for (s,m) in middle {
98 let start_time = s.time_stamp();
99 let ts = u64::from_be_bytes(start_time);
100 if let Some(r) = range.as_ref() {
101 if r.contains(&start_time){
102 content.push((ts,m))
103 }else {
104 match r.end_bound(){
105 std::ops::Bound::Included(x) if &start_time > x => break 'outer,
106 std::ops::Bound::Excluded(x) if &start_time >= x => break 'outer,
107 _ => (),
108 }
109 }
110 }else{
111 content.push((ts,m))
112 }
113 }
114 }
115 _ => break,
116 }
117 let res = read_magic_number(file, false);
118 if res.is_err(){break}
119 }
120 Ok(content)
121}