diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 140 |
1 files changed, 120 insertions, 20 deletions
@@ -1,15 +1,126 @@ | |||
1 | pub use directories::{ProjectDirs, UserDirs}; | 1 | //! `fondant` is a macro based library to take the boilerplate out of |
2 | pub use serde::{de::DeserializeOwned, Serialize}; | 2 | //! configuration handling. Most of `fondant` is based off the `confy` crate. |
3 | pub use serde_json; | 3 | //! |
4 | pub use serde_yaml; | 4 | //! `fondant` adds a couple of extra features: |
5 | pub 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 | ||
7 | use 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 | ||
89 | pub 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 | ||
111 | use serde::{de::DeserializeOwned, Serialize}; | ||
9 | #[derive(Debug)] | 112 | #[derive(Debug)] |
113 | /// Errors that `load` and `store` can result in | ||
10 | pub enum FondantError { | 114 | pub 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 | ||
20 | pub 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 | |||
34 | pub trait Configure: Serialize + DeserializeOwned + Default { | 132 | pub 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 | |||
137 | pub use fondant_derive::Configure; | ||