cmtool_core/ensight_gold/
reader.rs1use 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
13impl<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()?; if buffer.is_empty() {
68 Ok(true) } else {
70 Ok(false) }
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; pub type EnsightGoldReader = Reader<ENSIGHT_GOLDER_BINARY_FORMAT_LINE_SIZE>;