easy_configuration_format/
utils.rs

1use crate::Value;
2use std::collections::HashMap;
3
4
5
6/// Returns either the value as an str or a short error message
7pub fn get_str(setting_name: impl AsRef<str>, settings: &HashMap<String, Value>) -> Result<&str, String> {
8	get_value_as_type::<String>(setting_name, settings).map(|v| &**v)
9}
10
11/// Returns either the value as an string or a short error message
12pub fn get_string_mut(setting_name: impl AsRef<str>, settings: &mut HashMap<String, Value>) -> Result<&mut String, String> {
13	get_value_as_type_mut(setting_name, settings)
14}
15
16
17
18/// Returns either the value as an int or a short error message
19pub fn get_int(setting_name: impl AsRef<str>, settings: &HashMap<String, Value>) -> Result<i64, String> {
20	get_value_as_type(setting_name, settings).copied()
21}
22
23/// Returns either the value as an int or a short error message
24pub fn get_int_mut(setting_name: impl AsRef<str>, settings: &mut HashMap<String, Value>) -> Result<&mut i64, String> {
25	get_value_as_type_mut(setting_name, settings)
26}
27
28
29
30/// Returns either the value as an float or a short error message
31pub fn get_float(setting_name: impl AsRef<str>, settings: &HashMap<String, Value>) -> Result<f64, String> {
32	get_value_as_type(setting_name, settings).copied()
33}
34
35/// Returns either the value as an float or a short error message
36pub fn get_float_mut(setting_name: impl AsRef<str>, settings: &mut HashMap<String, Value>) -> Result<&mut f64, String> {
37	get_value_as_type_mut(setting_name, settings)
38}
39
40
41
42/// Returns either the value as an bool or a short error message
43pub fn get_bool(setting_name: impl AsRef<str>, settings: &HashMap<String, Value>) -> Result<bool, String> {
44	get_value_as_type(setting_name, settings).copied()
45}
46
47/// Returns either the value as an bool or a short error message
48pub fn get_bool_mut(setting_name: impl AsRef<str>, settings: &mut HashMap<String, Value>) -> Result<&mut bool, String> {
49	get_value_as_type_mut(setting_name, settings)
50}
51
52
53
54
55
56macro_rules! create_get_macro {
57	($get_name:ident, $($type_name_singular:ident)+) => {
58		#[macro_export]
59		/// Returns the value as an int or runs a block of code with `err` containing the error
60		macro_rules! $get_name {
61			($setting_name:expr, $settings:expr, $err_name:ident $err_block:block) => {
62				match easy_configuration_format::$get_name($setting_name, $settings) {
63					Ok(v) => v,
64					Err($err_name) => $err_block
65				}
66			};
67		}
68	};
69}
70
71create_get_macro!(get_str, a String);
72create_get_macro!(get_string_mut, a String);
73create_get_macro!(get_int, an Int);
74create_get_macro!(get_int_mut, an Int);
75create_get_macro!(get_float, a Float);
76create_get_macro!(get_float_mut, a Float);
77create_get_macro!(get_bool, a Bool);
78create_get_macro!(get_bool_mut, a Bool);
79
80
81
82
83
84/// Generic function for getting a setting value as a specific type
85pub fn get_value_as_type<T: FromEcfValue>(setting_name: impl AsRef<str>, settings: &HashMap<String, Value>) -> Result<&T, String> {
86	let setting_name = setting_name.as_ref();
87	let Some(value) = settings.get(setting_name) else {
88		return Err(format!("could not find setting \"{setting_name}\""));
89	};
90	let Some(output) = T::from_ecf_value(value) else {
91		return Err(format!("setting \"{setting_name}\" needs to be {}, but it currently is {}", T::TYPE_NAME_SINGULAR, value.type_as_singular_string()));
92	};
93	Ok(output)
94}
95
96/// Mutable version of get_value_as_type()
97pub fn get_value_as_type_mut<T: FromEcfValueMut>(setting_name: impl AsRef<str>, settings: &mut HashMap<String, Value>) -> Result<&mut T, String> {
98	let setting_name = setting_name.as_ref();
99	let Some(value) = settings.get_mut(setting_name) else {
100		return Err(format!("could not find setting \"{setting_name}\""));
101	};
102	let value_type_name_singular = value.type_as_singular_string(); // theoretically this shouldn't be needed here, but for some reason it isn't allowed in the else block
103	let Some(output) = T::from_ecf_value_mut(value) else {
104		return Err(format!("setting \"{setting_name}\" needs to be {}, but it currently is {}", T::TYPE_NAME_SINGULAR, value_type_name_singular));
105	};
106	Ok(output)
107}
108
109
110
111/// Converts an ecf::Value into a generic type
112pub trait FromEcfValue: Sized {
113	/// Name of the generic type, used for error messages, needs to be singular and uppercase (example: "a String")
114	const TYPE_NAME_SINGULAR: &'static str;
115	/// Main functionality
116	fn from_ecf_value(input: &Value) -> Option<&Self>;
117}
118
119/// Mutable version of FromEcfValue
120pub trait FromEcfValueMut: FromEcfValue {
121	/// Mutable version of FromEcfValue::from_ecf_value()
122	fn from_ecf_value_mut(input: &mut Value) -> Option<&mut Self>;
123}
124
125
126
127impl FromEcfValue for String {
128	const TYPE_NAME_SINGULAR: &'static str = "a String";
129	fn from_ecf_value(input: &Value) -> Option<&Self> {
130		if let Value::String (input_string) = input {
131			Some(input_string)
132		} else {
133			None
134		}
135	}
136}
137
138impl FromEcfValue for i64 {
139	const TYPE_NAME_SINGULAR: &'static str = "an Int";
140	fn from_ecf_value(input: &Value) -> Option<&Self> {
141		if let Value::I64 (input_i64) = input {
142			Some(input_i64)
143		} else {
144			None
145		}
146	}
147}
148
149impl FromEcfValue for f64 {
150	const TYPE_NAME_SINGULAR: &'static str = "a Float";
151	fn from_ecf_value(input: &Value) -> Option<&Self> {
152		if let Value::F64 (input_f64) = input {
153			Some(input_f64)
154		} else {
155			None
156		}
157	}
158}
159
160impl FromEcfValue for bool {
161	const TYPE_NAME_SINGULAR: &'static str = "a Bool";
162	fn from_ecf_value(input: &Value) -> Option<&Self> {
163		if let Value::Bool (input_bool) = input {
164			Some(input_bool)
165		} else {
166			None
167		}
168	}
169}
170
171
172
173impl FromEcfValueMut for String {
174	fn from_ecf_value_mut(input: &mut Value) -> Option<&mut Self> {
175		if let Value::String (input_string) = input {
176			Some(input_string)
177		} else {
178			None
179		}
180	}
181}
182
183impl FromEcfValueMut for i64 {
184	fn from_ecf_value_mut(input: &mut Value) -> Option<&mut Self> {
185		if let Value::I64 (input_i64) = input {
186			Some(input_i64)
187		} else {
188			None
189		}
190	}
191}
192
193impl FromEcfValueMut for f64 {
194	fn from_ecf_value_mut(input: &mut Value) -> Option<&mut Self> {
195		if let Value::F64 (input_f64) = input {
196			Some(input_f64)
197		} else {
198			None
199		}
200	}
201}
202
203impl FromEcfValueMut for bool {
204	fn from_ecf_value_mut(input: &mut Value) -> Option<&mut Self> {
205		if let Value::Bool (input_bool) = input {
206			Some(input_bool)
207		} else {
208			None
209		}
210	}
211}