Skip to main content

cmtool_assemble/generators/
artefact.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3use crate::CMError;
4use cmtool_data::{
5    CMCase, CMCaseJson, CMCaseWriter, CMExportType, DEFAULT_CASE_FILE_NAME, PhaseCM, RawPhase,
6};
7use serde::{Deserialize, Serialize};
8use std::fmt;
9use std::path::PathBuf;
10
11#[derive(Serialize, Deserialize, Clone, Default)]
12pub struct GenerateContract {
13    case: CMCase,
14    liquid_phase: Option<RawPhase>,
15    gas_phase: Option<RawPhase>,
16    relative_path: Option<String>,
17}
18
19impl fmt::Debug for GenerateContract {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        f.debug_struct("GenerateContract").finish()
22    }
23}
24
25fn format_path_case(relative_path: &Option<String>, file_name: &str) -> PathBuf {
26    relative_path
27        .as_ref()
28        .map(|rel| std::path::Path::new(&rel).join(file_name))
29        .unwrap_or_else(|| std::path::Path::new(file_name).to_path_buf())
30}
31
32impl GenerateContract {
33    pub fn get_case(&self) -> &CMCase {
34        &self.case
35    }
36
37    pub fn new_single_phase(case: CMCase, phase: RawPhase, relative_path: Option<String>) -> Self {
38        if phase.identifier == PhaseCM::Liquid {
39            Self {
40                case,
41                liquid_phase: Some(phase),
42                gas_phase: None,
43                relative_path,
44            }
45        } else {
46            Self {
47                case,
48                liquid_phase: None,
49                gas_phase: Some(phase),
50                relative_path,
51            }
52        }
53    }
54
55    pub fn new(
56        case: CMCase,
57        liquid_phase: RawPhase,
58        gas_phase: Option<RawPhase>,
59        relative_path: Option<String>,
60    ) -> Self {
61        Self {
62            case,
63            liquid_phase: Some(liquid_phase),
64            gas_phase,
65            relative_path,
66        }
67    }
68
69    fn write_phase(
70        dest: impl AsRef<std::path::Path>,
71        case: &mut CMCase,
72        phase: RawPhase,
73        relative_path: Option<String>,
74    ) -> Result<(), CMError> {
75        let (flowp, volumep) = phase.write(dest.as_ref().to_str().expect("utf path"))?;
76
77        let flowp = format_path_case(&relative_path, &flowp);
78        let volumep = format_path_case(&relative_path, &volumep);
79
80        case.add(
81            CMExportType::Flow(phase.identifier).into(),
82            flowp.to_str().expect("UTF-8 path"),
83        );
84        case.add(
85            CMExportType::Volume(phase.identifier).into(),
86            volumep.to_str().expect("UTF-8 path"),
87        );
88
89        Ok(())
90    }
91
92    fn prepare_fs(&self, root_dir: impl AsRef<std::path::Path>) -> Result<PathBuf, CMError> {
93        let path = if let Some(p) = &self.relative_path {
94            root_dir.as_ref().join(p)
95        } else {
96            root_dir.as_ref().to_owned()
97        };
98        std::fs::create_dir_all(&path)?; //FIXME
99        Ok(path)
100    }
101
102    pub fn write(mut self, root_dir: impl AsRef<std::path::Path>) -> Result<CMCase, CMError> {
103        if self.liquid_phase.is_none() && self.gas_phase.is_none() {
104            return Err(CMError::Custom("No phase to write".to_owned()));
105        }
106
107        let path = self.prepare_fs(&root_dir)?;
108
109        if let Some(liquid_phase) = self.liquid_phase {
110            Self::write_phase(
111                &path,
112                &mut self.case,
113                liquid_phase,
114                self.relative_path.clone(),
115            )?;
116        }
117
118        if let Some(gas_phase) = self.gas_phase {
119            Self::write_phase(path, &mut self.case, gas_phase, self.relative_path.clone())?;
120        }
121
122        let case_path = root_dir.as_ref().join(DEFAULT_CASE_FILE_NAME);
123        CMCaseJson::write_case(self.case.clone(), &case_path)?;
124
125        Ok(self.case)
126    }
127}