aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs140
1 files changed, 120 insertions, 20 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 5da5bdb..95e09f5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,15 +1,126 @@
1pub use directories::{ProjectDirs, UserDirs}; 1//! `fondant` is a macro based library to take the boilerplate out of
2pub use serde::{de::DeserializeOwned, Serialize}; 2//! configuration handling. Most of `fondant` is based off the `confy` crate.
3pub use serde_json; 3//!
4pub use serde_yaml; 4//! `fondant` adds a couple of extra features:
5pub use toml; 5//!
6//! - support for json, yaml and toml
7//! - support for custom config paths
8//! - support for custom config file names
9//!
10//! ### Sample usage
11//!
12//! ```
13//! // the struct has to derive Serialize, Deserialize and Default
14//! #[derive(Configure, Serialize, Deserialize, Default)]
15//! #[config_file = "config.toml"]
16//! // |
17//! // `-- this attribute sets the file name to "config.toml"
18//! // `-- the file format to "toml"
19//! // `-- the file path to "default" (read the notes below)
20//! struct AppConfig {
21//! version: u32,
22//! port: u32,
23//! username: String,
24//! }
25//!
26//! fn main() {
27//! // use `load` (associated method) to load the config file
28//! let mut conf = AppConfig::load().unwrap();
29//!
30//! // do stuff with conf
31//! conf.version = 2;
32//!
33//! // call `store` to save changes
34//! conf.store().unwrap();
35//! }
36//! ```
37//! **Notes**:
38//! - `load` returns `Default::default` if the config file is not present, and stores
39//! a serialized `Default::default` at the specified path
40//! - the "default" config path varies by platform:
41//! * GNU/Linux: `$XDG_CONFIG_HOME/my_cool_crate/config.toml` (follows xdg spec)
42//! * MacOS: `$HOME/Library/Preferences/my_cool_crate/config.toml`
43//! * Windows: `{FOLDERID_RoamingAppData}\_project_path_\config`
44//!
45//! ### Customization
46//!
47//! Set your own filename, for ex.: `apprc`
48//!
49//! ```
50//! #[derive(Configure, Serialize, Deserialize, Default)]
51//! #[config_file = "apprc.toml"]
52//! struct AppConfig {
53//! // -- snip --
54//! }
55//! // effective path: $XDG_CONFIG_HOME/my_cool_crate/apprc.toml
56//! // effective format: toml
57//! ```
58//!
59//! Change file format to `yaml`, by changing the file extension.
60//! Supported extensions are `yaml`, `toml`, `json`:
61//! ```
62//! #[derive(Configure, Serialize, Deserialize, Default)]
63//! #[config_file = "config.yaml"]
64//! struct AppConfig {
65//! // -- snip --
66//! }
67//! // effective path: $XDG_CONFIG_HOME/my_cool_crate/config.yaml
68//! // effective format: yaml
69//! ```
70//!
71//! Override the default config path, for ex.: the home directory
72//! (it is not recommended to override config path):
73//! ```
74//! #[derive(Configure, Serialize, Deserialize, Default)]
75//! #[config_file = "~/.apprc.json"]
76//! struct AppConfig {
77//! // -- snip --
78//! }
79//! // effective path: $HOME/.apprc.json
80//! // effective format: json
81//! ```
6 82
7use std::path::{Path, PathBuf}; 83/// Re-exporting crates that fondant_derive depends on.
84///
85///
86/// Unfortunately, this seems to be the only way to bring crates into
87/// scope from a proc-macro crate
88/// This module should not bother you
89pub mod fondant_exports {
90 pub use directories::{ProjectDirs, UserDirs};
91 pub use serde::{de::DeserializeOwned, Serialize};
92 pub use serde_json;
93 pub use serde_yaml;
94 use std::path::{Path, PathBuf};
95 pub use toml;
96 pub fn expand_tilde<P: AsRef<Path>>(path: P) -> PathBuf {
97 let p = path.as_ref();
98 if p.starts_with("~") {
99 if p == Path::new("~") {
100 return UserDirs::new().unwrap().home_dir().to_path_buf();
101 } else {
102 let mut h = UserDirs::new().unwrap().home_dir().to_path_buf();
103 h.push(p.strip_prefix("~/").unwrap());
104 return h;
105 }
106 }
107 return p.to_path_buf();
108 }
109}
8 110
111use serde::{de::DeserializeOwned, Serialize};
9#[derive(Debug)] 112#[derive(Debug)]
113/// Errors that `load` and `store` can result in
10pub enum FondantError { 114pub enum FondantError {
115 /// Occurs when the home dir is not accessible.
116 /// You should probably `panic!` when this is thrown.
11 InvalidHomeDir, 117 InvalidHomeDir,
118
119 /// Invalid toml/yaml/json config.
12 ConfigParseError, 120 ConfigParseError,
121
122 /// Invalid permissions to create config dir.
123 /// Might occur when you set config dir to, say, `/etc/config.toml` and run without superuser.
13 DirCreateErr(std::io::Error), 124 DirCreateErr(std::io::Error),
14 LoadError, 125 LoadError,
15 FileWriteError, 126 FileWriteError,
@@ -17,21 +128,10 @@ pub enum FondantError {
17 FileOpenError, 128 FileOpenError,
18} 129}
19 130
20pub fn expand_tilde<P: AsRef<Path>>(path: P) -> PathBuf { 131/// Derive this trait on a struct to mark it as a 'configuration' struct.
21 let p = path.as_ref();
22 if p.starts_with("~") {
23 if p == Path::new("~") {
24 return UserDirs::new().unwrap().home_dir().to_path_buf();
25 } else {
26 let mut h = UserDirs::new().unwrap().home_dir().to_path_buf();
27 h.push(p.strip_prefix("~/").unwrap());
28 return h;
29 }
30 }
31 return p.to_path_buf();
32}
33
34pub trait Configure: Serialize + DeserializeOwned + Default { 132pub trait Configure: Serialize + DeserializeOwned + Default {
35 fn load() -> Result<Self, FondantError>; 133 fn load() -> Result<Self, FondantError>;
36 fn store(&self) -> Result<(), FondantError>; 134 fn store(&self) -> Result<(), FondantError>;
37} 135}
136
137pub use fondant_derive::Configure;