cmtool_core/ensight_gold/
case.rs1use 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"); 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(); 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}