winsfs_core/io/shuffle/
reader.rs1use std::{
2 fs::File,
3 io::{self, Seek},
4 path::Path,
5};
6
7use byteorder::{ReadBytesExt, LE};
8
9use crate::{
10 io::{ReadSite, ReadStatus, Rewind},
11 saf::Site,
12};
13
14use super::{to_u64, Header};
15
16pub struct Reader<const D: usize, R> {
18 inner: R,
19 header: Header,
20}
21
22impl<const D: usize, R> Reader<D, R>
24where
25 R: io::BufRead,
26{
27 pub fn get(&self) -> &R {
29 &self.inner
30 }
31
32 pub fn get_mut(&mut self) -> &mut R {
34 &mut self.inner
35 }
36
37 pub fn header(&self) -> &Header {
39 &self.header
40 }
41
42 pub fn into_inner(self) -> R {
44 self.inner
45 }
46
47 pub fn new(reader: R, header: Header) -> Self {
51 Self {
52 inner: reader,
53 header,
54 }
55 }
56
57 pub fn read_header(&mut self) -> io::Result<Header> {
61 Header::read(&mut self.inner)
62 }
63}
64
65impl<const D: usize, R> io::Seek for Reader<D, R>
66where
67 R: io::BufRead + io::Seek,
68{
69 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
70 self.inner.seek(pos)
71 }
72}
73
74impl<const D: usize> Reader<D, io::BufReader<File>> {
75 pub fn try_from_path<P>(path: P) -> io::Result<Self>
81 where
82 P: AsRef<Path>,
83 {
84 let mut reader = File::open(path).map(io::BufReader::new)?;
85
86 let header = Header::read(&mut reader)?;
87 let header_dimension = header.shape().len();
88
89 if header_dimension == D {
90 Ok(Self::new(reader, header))
91 } else {
92 let msg = format!(
93 "shuffled SAF file header with dimension {header_dimension} \
94 did not match provided dimension {D}"
95 );
96 Err(io::Error::new(io::ErrorKind::InvalidData, msg))
97 }
98 }
99}
100
101impl<const D: usize, R> Rewind for Reader<D, R>
102where
103 R: io::BufRead + io::Seek,
104{
105 fn is_done(&mut self) -> io::Result<bool> {
106 self.inner.fill_buf().map(|b| b.is_empty())
109 }
110
111 fn rewind(&mut self) -> io::Result<()> {
112 self.seek(io::SeekFrom::Start(to_u64(self.header.header_size())))
113 .map(|_| ())
114 }
115}
116
117impl<const D: usize, R> ReadSite for Reader<D, R>
118where
119 R: io::BufRead + io::Seek,
120{
121 type Site = Site<D>;
122
123 fn read_site(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
124 let status = self.read_site_unnormalised(buf)?;
125
126 buf.iter_mut().for_each(|x| *x = x.exp());
127
128 Ok(status)
129 }
130
131 fn read_site_unnormalised(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
132 if ReadStatus::check(&mut self.inner)?.is_done() {
133 return Ok(ReadStatus::Done);
134 }
135
136 self.inner.read_f32_into::<LE>(buf.as_mut_slice())?;
137
138 Ok(ReadStatus::NotDone)
139 }
140}