1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! Disk: [`serde`](https://docs.rs/serde) + [`directories`](https://docs.rs/directories) + a whole bunch of file formats as [`Traits`](https://doc.rust-lang.org/book/ch10-02-traits.html).
//!
//! This crate is for (de)serializing to/from various file formats (provided by `serde`) to/from disk locations that follow OS-specific specifications/conventions (provided by `directories`). All errors returned will be an [`anyhow::Error`].
//!
//! Example of data being saved on the user's disk for future use:
//! ```
//! use disk::prelude::*;       // Necessary imports to get things working.
//! use disk::{Toml,toml_file}; // <- TOML trait & macro.
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Serialize,Deserialize)] // <- Your data must implement `serde`.
//! struct State {
//! 	string: String,
//! 	number: u32,
//! }
//! // To make this struct a file, use the following macro:
//! //
//! // |- 1. The file format used will be TOML.
//! // |
//! // |          |- 2. The struct "State" will be used.
//! // |          |
//! // |          |      |- 3. It will be saved in the OS Data directory.
//! // |          |      |
//! // |          |      |          |- 4. The main project directory is called "MyProject".
//! // |          |      |          |
//! // |          |      |          |            |- 6. It won't be in any sub-directories.
//! // |          |      |          |            |
//! // |          |      |          |            |   |- 7. The file name will be "state.toml".
//! // v          v      v          v            v   v
//!    toml_file!(State, Dir::Data, "MyProject", "", "state");
//!
//! // Now our `State` struct implements the `Toml` trait.
//! //
//! // The PATH would look something like:
//! // Windows | C:\Users\Alice\AppData\Roaming\My_Project\state.toml
//! // macOS   | /Users/Alice/Library/Application Support/My-Project/state.toml
//! // Linux   | /home/alice/.local/share/myproject/state.toml
//!
//! // I'd like to save this to disk, since I'll use it next time.
//! let my_state = State { string: "Hello".to_string(), number: 123 };
//!
//! // Since our `State` struct implements the `Toml` trait, it can do that:
//! match my_state.write() {
//! 	Ok(_) => println!("We saved to disk"),
//! 	Err(e) => eprintln!("We failed to save to disk"),
//! }
//!
//! // Let's create a new `State` by reading the file that we just created:
//! let new_state = State::from_file().expect("Failed to read disk");
//!
//! // These should be the same.
//! assert!(my_state == new_state);
//! ```
//! Manually implementing these traits is possible as well, it requires 4 constants to be defined.
//!
//! The file extension (`.bin`, `.toml`, `.json`, `.bson`, etc) is inferred based on what trait you use.
//! ```
//! impl disk::Toml for State {
//!     // Which OS directory it will be saved in.
//! 	const OS_DIRECTORY: disk::Dir = disk::Dir::Data;
//!     // Which the main project directory is called.
//! 	const PROJECT_DIRECTORY: &'static str = "MyProject";
//!     // If it should be in any sub-directories.
//!     const SUB_DIRECTORIES: &'static str = ""
//!     // What the saved filename will be.
//! 	const FILE_NAME: &'static str = "state";
//! }
//! ```
//!
//! Either a single or multiple sub-directories can be specified with a `/` delimiter.
//!
//! `\` is also allowed but ONLY if building on Windows.
//!
//! An empty string `""` means NO sub directories.
//! ```
//! # use disk::Dir::Data;
//! // Windows ... C:\Users\Alice\AppData\Roaming\My_Project\sub1\sub2\state.toml
//! toml_file!(State, Data, "MyProject", r"sub1\sub2", "state");
//!
//! // macOS ... /Users/Alice/Library/Application Support/My-Project/sub1/sub2/state.json
//! json_file!(State, Data, "MyProject", "sub1/sub2", "state");
//!
//! // Linux ... /home/alice/.local/share/myproject/sub1/sub2/state.yml
//! yaml_file!(State, Data, "MyProject", "sub1/sub2", "state");
//!
//! // NO sub directory:
//! toml_file!(State, Data, "MyProject", "", "state");
//! ```
//!
//! # File Formats
//! | File Format | Feature flag to enable |
//! |-------------|------------------------|
//! | Bincode     | `bincode`
//! | JSON        | `json`
//! | TOML        | `toml`
//! | YAML        | `yaml`
//! | Pickle      | `pickle`
//! | MessagePack | `messagepack`
//! | BSON        | `bson`
//! | Plain Text  | `plain`


//
// The "project" directory is taken from the `CARGO_PKG_NAME` environment variable, which should match the `[package.name]` key in your `Cargo.toml`, for example:
// ```toml
// [package]
// name = "my_project"
// ```
// This would create a directory like so:
// ```text
// Windows | C:\Users\Alice\AppData\Roaming\My_Project\
// macOS   | /Users/Alice/Library/Application Support/My-Project/
// Linux   | /home/alice/.local/share/myproject/
// ```

mod common;
//pub use disk_derive::*;
pub mod prelude {
	pub use crate::common::Dir as Dir;
	pub use const_format::assertcp as const_assert;
	pub use const_format::formatcp as const_format;
}

#[cfg(feature = "bincode")]
mod bincode;
#[cfg(feature = "bincode")]
pub use crate::bincode::Bincode as Bincode;

#[cfg(feature = "json")]
mod json;
#[cfg(feature = "json")]
pub use crate::json::Json as Json;

#[cfg(feature = "toml")]
mod toml;
#[cfg(feature = "toml")]
pub use crate::toml::Toml as Toml;

#[cfg(feature = "yaml")]
mod yaml;
#[cfg(feature = "yaml")]
pub use crate::yaml::Yaml as Yaml;

#[cfg(feature = "pickle")]
mod pickle;
#[cfg(feature = "pickle")]
pub use crate::pickle::Pickle as Pickle;

#[cfg(feature = "messagepack")]
mod messagepack;
#[cfg(feature = "messagepack")]
pub use crate::messagepack::MessagePack as MessagePack;

#[cfg(feature = "bson")]
mod bson;
#[cfg(feature = "bson")]
pub use crate::bson::Bson as Bson;

#[cfg(feature = "plain")]
mod plain;
#[cfg(feature = "plain")]
pub use crate::plain::Plain as Plain;