easy_configuration_format/
lib.rs

1//! # Easy Configuration Format
2//! 
3//! ### A settings format that strikes a great balance between usage simplicity and parsing simplicity, with aspects like:
4//! - Support for strings, ints, float, bools, and comments
5//! - 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`)
6//! - 'Setting updater' functions have built-in support and encouragement
7//! - Almost no code (~500 sloc) and no dependencies (other than std)
8//! 
9//! <br>
10//! 
11//! ## Example settings file:
12//! 
13//! ```txt
14//! format 1
15//! # This first line defines the version number of your settings file. If you want to update
16//! # your program's settings, this will allow you to update users' settings file to your
17//! # newer version
18//! 
19//! example key: "example value"
20//! 
21//! example blank: empty
22//! example string: "not empty"
23//! example int: 3
24//! example float: 3.5
25//! example bool: true
26//! example multiline: "
27//! "first line (#0)
28//! "also, because of how strings are stored, you can have " characters inside a string with
29//! "no escape codes needed
30//! "last line (#3)
31//! example string 2: "you can also put " chars in single-line strings"
32//! 
33//! example namespace.example key: "example value 2"
34//! # "namespaces" are entirely made up, they're just fancy names but it's still the
35//! # recommended way to structure settings
36//! 
37//! # example comment
38//! 
39//! ##
40//! example multiline comment
41//! just like strings, you can have extra # chars anywhere you want (as long as you don't 
42//! want one of the lines in a comment to just be "##")
43//! ##
44//! 
45//! example array.0: "value 0"
46//! example array.1: "value 1"
47//! example array.2: "value 2"
48//! example array.3: "value 3"
49//! 
50//! example nested array.0.name: "person 0"
51//! example nested array.0.age: "age 0"
52//! example nested array.0.friends.0: "person 1"
53//! example nested array.0.friends.1: "person 2"
54//! 
55//! example nested array.1.name: "person 1"
56//! example nested array.1.age: "age 1"
57//! example nested array.1.friends.0: "person 0"
58//! example nested array.1.friends.1: "person 2"
59//! 
60//! 
61//! 
62//! # examples for error handling:
63//! 
64//! example duplicate key: "this key will be kept"
65//! example duplicate key: "this key will be commented"
66//! 
67//! invalid key "doesn't have any colon"
68//! invalid value 1: "missing an ending quote
69//! invalid value 2: missing a starting quote"
70//! invalid value 3: missing both quotes
71//! # empty multiline strings aren't allowed:
72//! invalid value 4: "
73//! 
74//! invalid value 6: .3
75//! 
76//! invalid entry: empty # inline comments aren't allowed
77//! 
78//! ##
79//! invalid multiline comment, only these two lines will be commented because of this
80//! 
81//! # single-line comments cannot be invalid!
82//! 
83//! working key: "and even after all that, it can still keep parsing settings!"
84//! 
85//! ```
86//! 
87//! ### See the specification [Here](specification.txt)
88//! 
89//! <br>
90//! <br>
91//! <br>
92//! 
93//! 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.
94//! 
95//! 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).
96//! 
97//! <br>
98//! <br>
99
100
101
102#![warn(missing_docs)]
103
104#![feature(anonymous_lifetime_in_impl_trait)]
105
106
107
108/// This is the main operation of this crate. An ecf File is an instance of a configuration and its formatting.
109pub mod file;
110pub use file::*;
111/// Miscellaneous data used by the crate
112pub mod data;
113pub use data::*;
114/// All errors defined by the crate
115pub mod errors;
116pub use errors::*;
117
118
119
120/// Slightly easier way to create a new `ecf::Value::Empty`
121pub const fn empty() -> Value {
122	Value::Empty
123}
124
125/// Slightly easier way to create a new `ecf::Value::I64()`
126pub const fn i64(v: i64) -> Value {
127	Value::I64 (v)
128}
129
130/// Slightly easier way to create a new `ecf::Value::I64()`
131/// 
132/// This isn't marked as `const` because it gives an error for const trait functions
133pub fn to_i64(v: impl ToI64) -> Value {
134	Value::I64 (v.to_i64())
135}
136
137/// Slightly easier way to create a new `ecf::Value::F64()`
138pub const fn f64(v: f64) -> Value {
139	Value::F64 (v)
140}
141
142/// Slightly easier way to create a new `ecf::Value::F64()`
143/// 
144/// This isn't marked as `const` because it gives an error for const trait functions
145pub fn to_f64(v: impl ToF64) -> Value {
146	Value::F64 (v.to_f64())
147}
148
149/// Slightly easier way to create a new `ecf::Value::Bool()`
150pub const fn bool(v: bool) -> Value {
151	Value::Bool (v)
152}
153
154/// Slightly easier way to create a new `ecf::Value::String()`
155/// 
156/// This isn't marked as `const` because it works with strings
157pub fn string(v: impl ToString) -> Value {
158	Value::String (v.to_string())
159}
160
161
162
163/// Used for `ecf::to_i64()` overloading
164pub trait ToI64 {
165	/// Purpose of trait
166	fn to_i64(self) -> i64;
167}
168
169macro_rules! impl_to_i64 {
170	($impl_type:ty) => {
171		impl ToI64 for $impl_type {
172			fn to_i64(self) -> i64 {
173				self as i64
174			}
175		}
176	};
177}
178
179impl_to_i64!(i8);
180impl_to_i64!(u8);
181impl_to_i64!(i16);
182impl_to_i64!(u16);
183impl_to_i64!(i32);
184impl_to_i64!(u32);
185impl_to_i64!(i64);
186impl_to_i64!(u64);
187impl_to_i64!(i128);
188impl_to_i64!(u128);
189impl_to_i64!(isize);
190impl_to_i64!(usize);
191impl_to_i64!(f32);
192impl_to_i64!(f64);
193
194
195
196/// Used for `ecf::to_f64()` overloading
197pub trait ToF64 {
198	/// Purpose of trait
199	fn to_f64(self) -> f64;
200}
201
202macro_rules! impl_to_f64 {
203	($impl_type:ty) => {
204		impl ToF64 for $impl_type {
205			fn to_f64(self) -> f64 {
206				self as f64
207			}
208		}
209	};
210}
211
212impl_to_f64!(i8);
213impl_to_f64!(u8);
214impl_to_f64!(i16);
215impl_to_f64!(u16);
216impl_to_f64!(i32);
217impl_to_f64!(u32);
218impl_to_f64!(i64);
219impl_to_f64!(u64);
220impl_to_f64!(i128);
221impl_to_f64!(u128);
222impl_to_f64!(isize);
223impl_to_f64!(usize);
224impl_to_f64!(f32);
225impl_to_f64!(f64);