fluvio_types/
config_file.rs

1use std::fmt::Debug;
2use std::io::Error as IoError;
3use std::io::Write;
4use std::path::Path;
5use std::fs::{File, read_to_string};
6
7use tracing::debug;
8use serde::{Serialize, de::DeserializeOwned};
9use thiserror::Error;
10
11#[derive(Debug, Error)]
12pub enum LoadConfigError {
13    #[error("IoError: {0}")]
14    IoError(IoError),
15    #[error("TomlError: {0}")]
16    TomlError(toml::de::Error),
17}
18
19pub trait SaveLoadConfig {
20    fn save_to<T: AsRef<Path>>(&self, path: T) -> Result<(), IoError>;
21    fn load_from<T: AsRef<Path>>(path: T) -> Result<Self, LoadConfigError>
22    where
23        Self: Sized;
24    fn load_str(config: &str) -> Result<Self, LoadConfigError>
25    where
26        Self: Sized;
27}
28
29impl<S> SaveLoadConfig for S
30where
31    S: Serialize + DeserializeOwned + Debug,
32{
33    // save to file
34    fn save_to<T: AsRef<Path>>(&self, path: T) -> Result<(), IoError> {
35        let path_ref = path.as_ref();
36        debug!("saving config: {:#?} to: {:#?}", self, path_ref);
37        let toml = toml::to_string(self).map_err(|err| IoError::other(format!("{err}")))?;
38
39        let mut file = File::create(path_ref)?;
40        file.write_all(toml.as_bytes())?;
41        // On windows flush() is noop, but sync_all() calls FlushFileBuffers.
42        file.sync_all()
43    }
44
45    fn load_from<T: AsRef<Path>>(path: T) -> Result<Self, LoadConfigError> {
46        let path_ref = path.as_ref();
47        debug!(?path_ref, "loading from");
48
49        let file_str = read_to_string(path_ref).map_err(LoadConfigError::IoError)?;
50
51        let config = toml::from_str(&file_str).map_err(LoadConfigError::TomlError)?;
52        Ok(config)
53    }
54
55    fn load_str(config: &str) -> Result<Self, LoadConfigError>
56    where
57        Self: Sized,
58    {
59        let config = toml::from_str(config).map_err(LoadConfigError::TomlError)?;
60        Ok(config)
61    }
62}