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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//! # Easy Configuration Format
//!
//! ### A settings format that strikes a great balance between usage simplicity and parsing simplicity, with aspects like:
//! - Support for strings, ints, float, bools, and comments
//! - Elegant error handling, an invalid line in the middle won't ruin everything afterwards and loading then saving a file will always result in a valid ecf file (to see this in action, just run `cargo run --example main`)
//! - 'Setting updater' functions have built-in support and encouragement
//! - Almost no code (~500 sloc) and no dependencies (other than std)
//!
//! <br>
//!
//! ## Example settings file:
//!
//! ```txt
//! format 1
//! # This first line defines the version number of your settings file. If you want to update
//! # your program's settings, this will allow you to update users' settings file to your
//! # newer version
//!
//! example key: "example value"
//!
//! example blank: empty
//! example string: "not empty"
//! example int: 3
//! example float: 3.5
//! example bool: true
//! example multiline: "
//! "first line (#0)
//! "also, because of how strings are stored, you can have " characters inside a string with
//! "no escape codes needed
//! "last line (#3)
//! example string 2: "you can also put " chars in single-line strings"
//!
//! example namespace.example key: "example value 2"
//! # "namespaces" are entirely made up, they're just fancy names but it's still the
//! # recommended way to structure settings
//!
//! # example comment
//!
//! ##
//! example multiline comment
//! just like strings, you can have extra # chars anywhere you want (as long as you don't
//! want one of the lines in a comment to just be "##")
//! ##
//!
//! example array.0: "value 0"
//! example array.1: "value 1"
//! example array.2: "value 2"
//! example array.3: "value 3"
//!
//! example nested array.0.name: "person 0"
//! example nested array.0.age: "age 0"
//! example nested array.0.friends.0: "person 1"
//! example nested array.0.friends.1: "person 2"
//!
//! example nested array.1.name: "person 1"
//! example nested array.1.age: "age 1"
//! example nested array.1.friends.0: "person 0"
//! example nested array.1.friends.1: "person 2"
//!
//!
//!
//! # examples for error handling:
//!
//! example duplicate key: "this key will be kept"
//! example duplicate key: "this key will be commented"
//!
//! invalid key "doesn't have any colon"
//! invalid value 1: "missing an ending quote
//! invalid value 2: missing a starting quote"
//! invalid value 3: missing both quotes
//! # empty multiline strings aren't allowed:
//! invalid value 4: "
//!
//! invalid value 6: .3
//!
//! invalid entry: empty # inline comments aren't allowed
//!
//! ##
//! invalid multiline comment, only these two lines will be commented because of this
//!
//! # single-line comments cannot be invalid!
//!
//! working key: "and even after all that, it can still keep parsing settings!"
//!
//! ```
//!
//! ### See the specification [Here](specification.txt)
//!
//! <br>
//! <br>
//! <br>
//!
//! A settings file is intended to be represented in code using two main values: the layout vec and the values hashmap. The layout vec describes the layout of the settings file according to how it was when it was parsed, and modifying it at runtime isn't recommended (because there should no need to do so). The values hashmap simply stores the key-value (String, ecf::Value) pairs, and this is what your code will interact with.
//!
//! Also, I strongly recommend using a format updating system like what's shown in the [example](https://github.com/What42Pizza/Easy-Configuration-Format/blob/main/examples/main.rs).
//!
//! <br>
//! <br>
/// This is the main operation of this crate. An ecf File is an instance of a configuration and its formatting.
pub use *;
/// Miscellaneous data used by the crate
pub use *;
/// All errors defined by the crate
pub use *;
/// Slightly easier way to create a new `ecf::Value::Empty`
pub const
/// Slightly easier way to create a new `ecf::Value::I64()`
pub const
/// Slightly easier way to create a new `ecf::Value::I64()`
///
/// This isn't marked as `const` because it gives an error for const trait functions
/// Slightly easier way to create a new `ecf::Value::F64()`
pub const
/// Slightly easier way to create a new `ecf::Value::F64()`
///
/// This isn't marked as `const` because it gives an error for const trait functions
/// Slightly easier way to create a new `ecf::Value::Bool()`
pub const
/// Slightly easier way to create a new `ecf::Value::String()`
///
/// This isn't marked as `const` because it works with strings
/// Used for `ecf::to_i64()` overloading
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
impl_to_i64!;
/// Used for `ecf::to_f64()` overloading
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;
impl_to_f64!;