1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::error::CascError;
use crate::utility::dsv_file::DSVFile;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
/// Represents build information loaded from a CASC `.build.info` file.
#[derive(Debug)]
pub struct CascBuildInfo {
variables: HashMap<String, Variable>,
}
/// Represents a variable entry in the build info.
#[derive(Debug)]
pub(crate) struct Variable {
pub(crate) name: String,
pub(crate) var_type: String,
pub(crate) value: String,
}
impl Variable {
/// Creates a new `Variable` with the given name, type, and value.
pub(crate) fn new(name: String, var_type: String, value: String) -> Self {
Variable {
name,
var_type,
value,
}
}
}
impl CascBuildInfo {
/// Creates a new, empty `CascBuildInfo`.
pub(crate) fn new() -> Self {
CascBuildInfo {
variables: HashMap::new(),
}
}
/// Loads build info from the specified file and returns a new instance.
///
/// # Arguments
///
/// * `file_name` - The path to the `.build.info` file.
pub(crate) fn with_file(file_name: &PathBuf) -> Result<Self, CascError> {
let mut instance = CascBuildInfo::new();
instance.load(file_name)?;
Ok(instance)
}
/// Retrieves the value of a variable by name, or returns the provided default value if not found.
///
/// # Arguments
///
/// * `var_name` - The name of the variable to retrieve.
/// * `default_value` - The value to return if the variable is not found.
pub(crate) fn get(&self, var_name: &str, default_value: &str) -> String {
if let Some(var) = self.variables.get(var_name) {
var.value.clone()
} else {
default_value.to_string()
}
}
/// Loads build info variables from the specified file into this instance.
///
/// # Arguments
///
/// * `file_name` - The path to the `.build.info` file.
pub(crate) fn load<P: AsRef<Path>>(&mut self, file_name: P) -> Result<(), CascError> {
let dsv = DSVFile::from_file(file_name, "|", Some("#"))?;
let rows = dsv.rows;
if rows.len() < 2 {
return Err(CascError::FileCorrupted("Not enough rows".into()));
}
let header = &rows[0];
let data = &rows[1];
if header.len() != data.len() {
return Err(CascError::FileCorrupted(
"Header/data length mismatch".to_string(),
));
}
for (info, value) in header.iter().zip(data.iter()) {
let split: Vec<&str> = info.split('!').collect();
if split.len() < 2 {
return Err(CascError::FileCorrupted("Header format invalid".into()));
}
let var = Variable {
name: split[0].to_string(),
var_type: split[1].to_string(),
value: value.clone(),
};
self.variables.insert(split[0].to_string(), var);
}
Ok(())
}
}