Skip to main content

cmtool_core/ensight_gold/
reader.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3use std::fs::File;
4use std::io::BufReader;
5use std::io::ErrorKind;
6use std::io::SeekFrom;
7use std::io::prelude::*;
8use std::path::Path;
9use std::path::PathBuf;
10
11pub struct FileBuffer<const N: usize>([u8; N]);
12
13// impl<const N: usize> FileBuffer<N> {
14//     pub fn to_string(&self) -> String {
15//         let trimmed = match self.0.iter().position(|&b| b == 0) {
16//             Some(pos) => &self.0[..pos],
17//             None => &self.0[..],
18//         };
19
20//         String::from_utf8_lossy(trimmed).into_owned()
21//     }
22// }
23
24impl<const N: usize> std::fmt::Display for FileBuffer<N> {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        let trimmed = match self.0.iter().position(|&b| b == 0) {
27            Some(pos) => &self.0[..pos],
28            None => &self.0[..],
29        };
30
31        writeln!(f, "{}", String::from_utf8_lossy(trimmed).into_owned())
32    }
33}
34
35pub struct Reader<const N: usize> {
36    filepath: PathBuf,
37    reader: BufReader<File>,
38    line_buffer: FileBuffer<N>,
39}
40
41impl<const N: usize> Reader<N> {
42    pub fn new(path: impl AsRef<Path>) -> std::io::Result<Self> {
43        let filepath = path.as_ref().to_path_buf();
44        let fd = File::open(filepath.clone())?;
45        Ok(Reader {
46            filepath,
47            reader: BufReader::new(fd),
48            line_buffer: FileBuffer([0; N]),
49        })
50    }
51
52    pub fn path(&self) -> &Path {
53        &self.filepath
54    }
55
56    pub fn check_lines_contains(&mut self, name: &str) -> std::io::Result<()> {
57        if !self.get_line()?.to_string().contains(name) {
58            return Err(std::io::Error::new(
59                ErrorKind::Unsupported,
60                format!("Missing '{}' in header {:?}", name, self.filepath),
61            ));
62        }
63        Ok(())
64    }
65    pub fn check_eof(&mut self) -> std::io::Result<bool> {
66        let buffer = self.reader.fill_buf()?; //Fill_buff does not consum, keep current file position
67        if buffer.is_empty() {
68            Ok(true) // EOF
69        } else {
70            Ok(false) // Not EOF
71        }
72    }
73
74    fn get_line(&mut self) -> std::io::Result<&FileBuffer<N>> {
75        self.reader.read_exact(&mut self.line_buffer.0)?;
76        Ok(&self.line_buffer)
77    }
78
79    pub fn get_line_string(&mut self) -> std::io::Result<String> {
80        self.reader.read_exact(&mut self.line_buffer.0)?;
81        Ok(self.line_buffer.to_string())
82    }
83
84    pub fn ignore_line(&mut self) -> std::io::Result<()> {
85        self.ignore_bytes(N as i64)
86    }
87
88    pub fn ignore_bytes(&mut self, n: i64) -> std::io::Result<()> {
89        self.reader.seek(SeekFrom::Current(n))?;
90        Ok(())
91    }
92
93    pub fn rollback_n(&mut self, n: i64) -> std::io::Result<()> {
94        if n < 0 {
95            return Err(std::io::Error::new(
96                ErrorKind::Unsupported,
97                "Rollback parameter must be positive",
98            ));
99        }
100        self.reader.seek(SeekFrom::Current(-n))?;
101        Ok(())
102    }
103
104    pub fn rollback(&mut self) -> std::io::Result<()> {
105        self.rollback_n(80)
106    }
107
108    pub fn read_i32(&mut self) -> std::io::Result<i32> {
109        let mut buf = [0u8; 4];
110        self.reader.read_exact(&mut buf)?;
111        Ok(i32::from_le_bytes(buf))
112    }
113    pub fn read_f32(&mut self) -> std::io::Result<f32> {
114        let mut buf = [0u8; 4];
115        self.reader.read_exact(&mut buf)?;
116        Ok(f32::from_le_bytes(buf))
117    }
118
119    pub fn read_buffer_f32(&mut self, size: usize) -> std::io::Result<Vec<f32>> {
120        let mut raw_buf = vec![0u8; size * 4];
121        self.reader.read_exact(&mut raw_buf)?;
122
123        let float_buf: Vec<f32> = raw_buf
124            .chunks_exact(4)
125            .map(|bytes| {
126                let array = bytes.try_into().unwrap();
127                f32::from_le_bytes(array)
128            })
129            .collect();
130
131        Ok(float_buf)
132    }
133}
134const ENSIGHT_GOLDER_BINARY_FORMAT_LINE_SIZE: usize = 80; //Bytes;
135pub type EnsightGoldReader = Reader<ENSIGHT_GOLDER_BINARY_FORMAT_LINE_SIZE>;