Skip to main content

cmtool_core/ensight_gold/
case.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3use std::{
4    fs::File,
5    io::{BufRead, BufReader},
6    path::Path,
7};
8
9use crate::CoreError;
10
11#[derive(Clone, Copy, PartialEq, Eq)]
12pub enum VariableType {
13    Scalar,
14    Vector,
15}
16
17impl TryInto<VariableType> for String {
18    type Error = ();
19
20    fn try_into(self) -> Result<VariableType, Self::Error> {
21        match self {
22            val if val == *"scalar" => Ok(VariableType::Scalar),
23            val if val == *"vector" => Ok(VariableType::Vector),
24            _ => Err(()),
25        }
26    }
27}
28
29#[derive(Default, Debug, Clone)]
30pub struct VariableInfo {
31    pub var_type: String,
32    pub name: String,
33    pub filepath: String,
34}
35
36impl VariableInfo {
37    pub fn get_type(&self) -> VariableType {
38        self.var_type.clone().try_into().unwrap()
39    }
40
41    fn read(line: &str) -> std::io::Result<Self> {
42        let mut tokens = line.split_whitespace();
43        let mut var_info = VariableInfo::default();
44
45        if let Some(var_type) = tokens.next() {
46            var_info.var_type = var_type.to_string();
47        }
48
49        if var_info.var_type == "scalar" || var_info.var_type == "vector" {
50            tokens.next().expect("Error reading case"); // Skip "per"
51
52            if tokens.next().expect("Error reading case") != "element:" {
53                unimplemented!("Eg case Vector/Scalar: per node");
54            }
55        }
56
57        if let Some(name) = tokens.next() {
58            var_info.name = name.trim_matches('"').to_string();
59        }
60
61        if let Some(filepath) = tokens.next() {
62            var_info.filepath = filepath.trim_matches('"').to_string();
63        }
64
65        Ok(var_info)
66    }
67}
68
69#[derive(Debug)]
70pub struct Case {
71    pub geometry_file_path: String,
72    pub paths: Vec<VariableInfo>,
73    pub root: String,
74}
75
76impl Case {
77    fn read_from_buffer<R: std::io::Read>(
78        reader: &mut BufReader<R>,
79        case: &mut Case,
80    ) -> std::io::Result<()> {
81        let mut line = String::new();
82
83        loop {
84            line.clear();
85            if reader.read_line(&mut line)? == 0 {
86                break;
87            }
88
89            if line.contains("GEOMETRY") {
90                let mut next_line = String::new();
91                reader.read_line(&mut next_line)?;
92                let mut parts = next_line.split_whitespace();
93                parts.next(); // Skip "model:"
94                if let Some(path) = parts.next() {
95                    case.geometry_file_path = path.trim_matches('"').to_string();
96                }
97            }
98
99            if line.contains("VARIABLE") {
100                line.clear();
101                reader.read_line(&mut line)?;
102
103                while !(line.contains("SCRIPTS")
104                    || line.contains("MATERIAL")
105                    || line.contains("FILE")
106                    || line.contains("TIME"))
107                {
108                    case.paths.push(VariableInfo::read(&line)?);
109                    line.clear();
110                    if reader.read_line(&mut line)? == 0 {
111                        break;
112                    }
113                }
114            }
115        }
116
117        Ok(())
118    }
119
120    pub fn read(path: impl AsRef<Path>) -> Result<Case, CoreError> {
121        if let Some(root_path) = path.as_ref().parent() {
122            if let Some(root_str) = root_path.to_str() {
123                let root = root_str.to_string();
124                let mut case = Case {
125                    geometry_file_path: String::new(),
126                    paths: vec![],
127                    root,
128                };
129                let fd = File::open(path)?;
130                let mut buffer = BufReader::new(fd);
131
132                Self::read_from_buffer(&mut buffer, &mut case)?;
133
134                Ok(case)
135            } else {
136                Err(CoreError::Custom("Path is not valid UTF-8".to_owned()))
137            }
138        } else {
139            Err(CoreError::Custom("No parent directory".to_owned()))
140        }
141    }
142}