runner_manager_platform/
settings_file.rs1use std::io;
4use std::path::Path;
5
6use serde::Serialize;
7use serde::de::DeserializeOwned;
8
9pub fn load<T: Default + DeserializeOwned>(path: &Path) -> io::Result<T> {
15 match std::fs::read(path) {
16 Ok(bytes) => serde_json::from_slice(&bytes)
17 .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error)),
18 Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(T::default()),
19 Err(error) => Err(error),
20 }
21}
22
23pub fn save(path: &Path, value: &impl Serialize) -> io::Result<()> {
30 let bytes = serde_json::to_vec_pretty(value).map_err(io::Error::other)?;
31 crate::host_fitness::write_atomically(path, &bytes)
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[derive(Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
39 struct Example {
40 value: u8,
41 }
42
43 #[test]
44 fn a_missing_file_is_the_defaults_and_a_saved_one_reads_back() {
45 let directory = tempfile::tempdir().unwrap();
46 let path = directory.path().join("nested").join("example.json");
47 assert_eq!(load::<Example>(&path).unwrap(), Example::default());
48 save(&path, &Example { value: 7 }).unwrap();
49 assert_eq!(load::<Example>(&path).unwrap(), Example { value: 7 });
50 std::fs::write(&path, b"{").unwrap();
51 assert!(load::<Example>(&path).is_err());
52 }
53}