diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | fondant/Cargo.toml | 9 | ||||
-rw-r--r-- | fondant/src/lib.rs | 86 | ||||
-rw-r--r-- | fondant_deps/Cargo.toml | 19 | ||||
-rw-r--r-- | fondant_deps/src/lib.rs | 47 |
5 files changed, 162 insertions, 1 deletions
@@ -1,6 +1,6 @@ | |||
1 | # Generated by Cargo | 1 | # Generated by Cargo |
2 | # will have compiled files and executables | 2 | # will have compiled files and executables |
3 | /target/ | 3 | **/target/** |
4 | 4 | ||
5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries |
6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html |
diff --git a/fondant/Cargo.toml b/fondant/Cargo.toml new file mode 100644 index 0000000..d6886b1 --- /dev/null +++ b/fondant/Cargo.toml | |||
@@ -0,0 +1,9 @@ | |||
1 | [package] | ||
2 | name = "fondant" | ||
3 | version = "0.1.0" | ||
4 | authors = ["Akshay <[email protected]>"] | ||
5 | edition = "2018" | ||
6 | |||
7 | [dependencies] | ||
8 | fondant_derive = {version = "0.1.0", path = "../fondant_derive"} | ||
9 | fondant_deps = {version = "0.1.0", path = "../fondant_deps"} | ||
diff --git a/fondant/src/lib.rs b/fondant/src/lib.rs new file mode 100644 index 0000000..d5758dc --- /dev/null +++ b/fondant/src/lib.rs | |||
@@ -0,0 +1,86 @@ | |||
1 | //! `fondant` is a macro based library to take the boilerplate out of | ||
2 | //! configuration handling. Most of `fondant` is based off the `confy` crate. | ||
3 | //! | ||
4 | //! `fondant` adds a couple of extra features: | ||
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 | //! ``` | ||
82 | |||
83 | pub use fondant_deps::fondant_exports; | ||
84 | pub use fondant_deps::Configure; | ||
85 | pub use fondant_deps::FondantError; | ||
86 | pub use fondant_derive::Configure; | ||
diff --git a/fondant_deps/Cargo.toml b/fondant_deps/Cargo.toml new file mode 100644 index 0000000..2d1a2db --- /dev/null +++ b/fondant_deps/Cargo.toml | |||
@@ -0,0 +1,19 @@ | |||
1 | [package] | ||
2 | name = "fondant_deps" | ||
3 | version = "0.1.0" | ||
4 | authors = ["Akshay <[email protected]>"] | ||
5 | edition = "2018" | ||
6 | |||
7 | [dependencies] | ||
8 | toml = "^0.5" | ||
9 | serde_yaml = "0.8" | ||
10 | serde_json = "1.0.48" | ||
11 | directories = "2.0" | ||
12 | |||
13 | [dependencies.serde] | ||
14 | version = "1.0.103" | ||
15 | features = ["derive"] | ||
16 | |||
17 | [dependencies.syn] | ||
18 | version = "1.0" | ||
19 | features = ["full"] | ||
diff --git a/fondant_deps/src/lib.rs b/fondant_deps/src/lib.rs new file mode 100644 index 0000000..6f62ce8 --- /dev/null +++ b/fondant_deps/src/lib.rs | |||
@@ -0,0 +1,47 @@ | |||
1 | pub mod fondant_exports { | ||
2 | pub use directories::{ProjectDirs, UserDirs}; | ||
3 | pub use serde::{de::DeserializeOwned, Serialize}; | ||
4 | pub use serde_json; | ||
5 | pub use serde_yaml; | ||
6 | use std::path::{Path, PathBuf}; | ||
7 | pub use toml; | ||
8 | pub fn expand_tilde<P: AsRef<Path>>(path: P) -> PathBuf { | ||
9 | let p = path.as_ref(); | ||
10 | if p.starts_with("~") { | ||
11 | if p == Path::new("~") { | ||
12 | return UserDirs::new().unwrap().home_dir().to_path_buf(); | ||
13 | } else { | ||
14 | let mut h = UserDirs::new().unwrap().home_dir().to_path_buf(); | ||
15 | h.push(p.strip_prefix("~/").unwrap()); | ||
16 | return h; | ||
17 | } | ||
18 | } | ||
19 | return p.to_path_buf(); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | use serde::{de::DeserializeOwned, Serialize}; | ||
24 | #[derive(Debug)] | ||
25 | /// Errors that `load` and `store` can result in | ||
26 | pub enum FondantError { | ||
27 | /// Occurs when the home dir is not accessible. | ||
28 | /// You should probably `panic!` when this is thrown. | ||
29 | InvalidHomeDir, | ||
30 | |||
31 | /// Invalid toml/yaml/json config. | ||
32 | ConfigParseError, | ||
33 | |||
34 | /// Invalid permissions to create config dir. | ||
35 | /// Might occur when you set config dir to, say, `/etc/config.toml` and run without superuser. | ||
36 | DirCreateErr(std::io::Error), | ||
37 | LoadError, | ||
38 | FileWriteError, | ||
39 | FileReadError, | ||
40 | FileOpenError, | ||
41 | } | ||
42 | |||
43 | /// Derive this trait on a struct to mark it as a 'configuration' struct. | ||
44 | pub trait Configure: Serialize + DeserializeOwned + Default { | ||
45 | fn load() -> Result<Self, FondantError>; | ||
46 | fn store(&self) -> Result<(), FondantError>; | ||
47 | } | ||