Skip to main content

lgp/core/
characteristics.rs

1use std::{
2    error::Error,
3    fs::{read_to_string, OpenOptions},
4    io::Write,
5    path::{Path, PathBuf},
6};
7
8use serde::{de::DeserializeOwned, Serialize};
9use tracing;
10
11use crate::utils::misc::create_path;
12
13pub trait Load
14where
15    Self: Sized + DeserializeOwned,
16{
17    fn load(path: impl Into<PathBuf>) -> Self {
18        let contents = read_to_string(path.into()).unwrap();
19        let deserialized: Self = serde_json::from_str(&contents).unwrap();
20
21        deserialized
22    }
23}
24
25pub trait Save
26where
27    Self: Serialize,
28{
29    fn save(&self, path: &str) -> Result<String, Box<dyn Error>> {
30        create_path(path, true)?;
31
32        tracing::trace!(path = path, "Attempting JSON serialization");
33        let serialized = match serde_json::to_string_pretty(&self) {
34            Ok(s) => s,
35            Err(e) => {
36                tracing::error!(path = path, error = %e, "JSON serialization failed");
37                return Err(e.into());
38            }
39        };
40        tracing::trace!(
41            path = path,
42            bytes = serialized.len(),
43            "Serialization successful"
44        );
45
46        let mut file = OpenOptions::new()
47            .write(true)
48            .create(true)
49            .truncate(true)
50            .open(Path::new(path))?;
51
52        file.write_all(serialized.as_bytes())?;
53
54        Ok(serialized)
55    }
56}
57
58pub trait Reproduce: Load + Save {}
59
60impl<T> Load for T where T: Sized + DeserializeOwned {}
61impl<T> Save for T where T: Serialize {}
62impl<T> Reproduce for T where T: Load + Save {}