#![doc = include_str!("../README.md")]
pub mod args;
use rand::RngCore;
use serde::{de::DeserializeOwned, Serialize};
use std::{error::Error, path::Path};
use streambed::{decrypt_buf, encrypt_struct, secret_store};
use tokio::{
fs,
io::{AsyncReadExt, AsyncWriteExt},
};
pub async fn load_struct<T, D, DE>(
state_storage_path: &Path,
ss: &impl secret_store::SecretStore,
secret_path: &str,
deserialize: D,
) -> Result<T, Box<dyn Error>>
where
T: Default + DeserializeOwned,
D: FnOnce(&[u8]) -> Result<T, DE>,
{
if let Ok(mut f) = fs::File::open(state_storage_path).await {
let mut buf = vec![];
f.read_to_end(&mut buf).await?;
Ok(decrypt_buf(ss, secret_path, &mut buf, deserialize)
.await
.unwrap_or_default())
} else {
Ok(T::default())
}
}
pub async fn save_struct<T, U, F, S, SE>(
state_storage_path: &Path,
ss: &impl secret_store::SecretStore,
secret_path: &str,
serialize: S,
rng: F,
state: &T,
) -> Result<(), Box<dyn Error>>
where
T: Serialize,
S: FnOnce(&T) -> Result<Vec<u8>, SE>,
F: FnOnce() -> U,
U: RngCore,
{
if let Some(buf) = encrypt_struct(ss, secret_path, serialize, rng, state).await {
let mut f = fs::File::create(state_storage_path).await?;
f.write_all(&buf).await?;
}
Ok(())
}