1#![doc = include_str!("../README.md")]
2
3pub mod args;
4
5use rand::RngCore;
6use serde::{de::DeserializeOwned, Serialize};
7use std::{error::Error, path::Path};
8use streambed::{decrypt_buf, encrypt_struct, secret_store};
9use tokio::{
10 fs,
11 io::{AsyncReadExt, AsyncWriteExt},
12};
13
14pub async fn load_struct<T, D, DE>(
20 state_storage_path: &Path,
21 ss: &impl secret_store::SecretStore,
22 secret_path: &str,
23 deserialize: D,
24) -> Result<T, Box<dyn Error>>
25where
26 T: Default + DeserializeOwned,
27 D: FnOnce(&[u8]) -> Result<T, DE>,
28{
29 if let Ok(mut f) = fs::File::open(state_storage_path).await {
30 let mut buf = vec![];
31 f.read_to_end(&mut buf).await?;
32 Ok(decrypt_buf(ss, secret_path, &mut buf, deserialize)
33 .await
34 .unwrap_or_default())
35 } else {
36 Ok(T::default())
37 }
38}
39
40pub async fn save_struct<T, U, F, S, SE>(
42 state_storage_path: &Path,
43 ss: &impl secret_store::SecretStore,
44 secret_path: &str,
45 serialize: S,
46 rng: F,
47 state: &T,
48) -> Result<(), Box<dyn Error>>
49where
50 T: Serialize,
51 S: FnOnce(&T) -> Result<Vec<u8>, SE>,
52 F: FnOnce() -> U,
53 U: RngCore,
54{
55 if let Some(buf) = encrypt_struct(ss, secret_path, serialize, rng, state).await {
56 let mut f = fs::File::create(state_storage_path).await?;
57 f.write_all(&buf).await?;
58 }
59 Ok(())
60}