Skip to main content

fermah_common/fs/
json.rs

1use std::{future::Future, path::Path};
2
3use serde::{de::DeserializeOwned, Serialize};
4use tokio::fs;
5use tracing::{debug, error, info};
6
7use crate::fs::{ensure_dir, error::Error};
8
9/// A trait for deserializing from a JSON file, any type that implements Deserialize.
10pub trait Json: Sized {
11    fn from_json_path<P: AsRef<Path> + Send>(
12        path: P,
13    ) -> impl Future<Output = Result<Self, Error>> + Send
14    where
15        Self: DeserializeOwned,
16    {
17        async {
18            info!("reading {}", path.as_ref().display());
19
20            if !path.as_ref().exists() {
21                error!("file not found: {}", path.as_ref().display())
22            }
23            let file_contents = fs::read(path).await?;
24
25            debug!("{}", String::from_utf8_lossy(&file_contents));
26
27            let result = serde_json::from_slice(&file_contents)?;
28
29            Ok(result)
30        }
31    }
32
33    fn to_json_path<P: AsRef<Path> + Send>(
34        &self,
35        path: P,
36    ) -> impl Future<Output = Result<(), Error>>
37    where
38        Self: Serialize,
39    {
40        async {
41            let json = serde_json::to_string_pretty(self)?;
42            let parent = path.as_ref().parent().unwrap();
43            ensure_dir(&parent, None).await?;
44            fs::write(path, json).await?;
45            Ok(())
46        }
47    }
48}
49
50impl<T> Json for T where T: Serialize + DeserializeOwned {}