# toml_const TOML compile-time constants ## Getting started [Install the CLI](https://crates.io/crates/toml_const_cli). This generates some boilerplate files and code: ```sh cargo install toml_const_cli # use toml_const_cli init --help to view more options toml_const_cli init # path to Cargo.toml ``` Your package should now look like this: ```sh package ├── .cargo # generated/modified by CLI │ └── config.toml ├── .config # generated by CLI │   ├── .gitignore │   ├── package.debug.toml # debug variant │   ├── package.deploy.toml # deploy/release variant │   └── package.template.toml # defaults ├── src │ └── main.rs ├── .gitignore ├── build.rs # generated by CLI ├── generated.rs # generated by build.rs └── Cargo.toml ``` If you have an existing build script, add the following inside: ```rust // inside build.rs fn main() { toml_const::run(); // ... rest of your build script } ``` `generated.rs` can now be included into your code: ```rust include!("../generated.rs") // included in main, for example ``` It is recommended to include this file in a separate module: ```rust // inside main.rs / lib.rs mod consts; // inside consts.rs #![allow(unused)] include!("../generated.rs") ``` And then use it: ```rust let this: bool = consts::USE; // the USE const must always be defined ``` ## Explanation All valid TOML datatypes are generated as compile-time constants, except for tables/arrays that contain inner tables/arrays. Arrays and tables are defined inside a `lazy_static!` wrapper. All tables are destructured, when possible, to keys that point to their TOML values. Namespaces are separated with an underscore "`_`". ## Example ```toml [table] field = "string" time = 11:20:00 integer = 3 [table.inner] field = "another string" datetime = 1979-05-27 07:32:00Z one_billion = 1e09 [table.other] normal_array = [1, 2, 3, 4, 5, 6] [[arr_of_tables]] this = "foo" that = "bar" [[arr_of_tables]] this = "fizz" that = "buzz" [[arr_of_tables]] this = "pee" that = "poo" ``` ### Destructured variables ```rust // destructured first table let f: &str = TABLE_FIELD; let t: toml::value::Datetime = TABLE_TIME; let i: i64 = TABLE_INTEGER; // destructured second table let tif: &str = TABLE_INNER_FIELD; let tidt: toml::value::Datetime = TABLE_INNER_DATETIME; let tib: i64 = TABLE_INNER_ONE_BILLION; ``` ### Tables Last-level tables, or tables that do not contain inner tables or arrays, also have their key-value pairs stored as a `HashMap<&'static str, String>`: ```rust /// `table` does not have an associated hashmap, as it contains /// an inner table `table.inner`. /// /// The associatd hashmap for `table.inner` is TABLE_INNER. let ht: &HashMap<&'static str, String> = &*TABLE_INNER; // hashmaps lose type-specific information let tif_string: &str = TABLE_INNER.get("FIELD").unwrap(); let tidt_string: &str = TABLE_INNER.get("DATETIME").unwrap(); let tib_string: &str = TABLE_INNER.get("ONE_BILLION").unwrap(); // but you can iterate over them at runtime for key in TABLE_INNER.keys() { // ... } ``` ### Arrays Arrays can also be used. The type for all elements is inferred from the first element. ```rust // iterate over array elements for item: &i64 in TABLE_OTHER_NORMAL_ARRAY.iter() { // ... } // iterate over array of tables for subtable: &HashMap<&'static str, String> in ARR_OF_TABLES.iter() { // ... } ```
Generated code ```rust // ...imports excluded /// type: &'static str pub const TABLE_INNER_FIELD: &'static str = "another string"; /// type: f64 pub const TABLE_INNER_ONE_BILLION: f64 = (1000000000_f64); /// type: i64 pub const TABLE_INTEGER: i64 = (3_i64); lazy_static::lazy_static! { /// type: [HashMap<&'static str, String>; 3] pub static ref ARR_OF_TABLES: [HashMap<&'static str, String>; 3] = [ HashMap::from([ ("that", "bar".to_string()),("this", "foo".to_string()),]) , HashMap::from([ ("that", "buzz".to_string()),("this", "fizz".to_string()),]) , HashMap::from([ ("that", "poo".to_string()),("this", "pee".to_string()),]) ]; } /// type: &'static str pub const TABLE_FIELD: &'static str = "string"; /// type: bool pub const USE: bool = false; /// type: Datetime pub const TABLE_TIME: Datetime = Datetime { date: None, time: Some(Time { hour: 11, minute: 20, second: 0, nanosecond: 0, }), offset: None, }; lazy_static::lazy_static! { /// type: [i64; 6] pub static ref OTHER_NORMAL_ARRAY: [i64; 6] = [ (1_i64), (2_i64), (3_i64), (4_i64), (5_i64), (6_i64) ]; } /// type: Datetime pub const TABLE_INNER_DATETIME: Datetime = Datetime { date: Some(Date { year: 1979, month: 5, day: 27, }), time: Some(Time { hour: 7, minute: 32, second: 0, nanosecond: 0, }), offset: Some(Offset::Z), }; lazy_static::lazy_static! { /// type: HashMap<&'static str, String> pub static ref TABLE_INNER: HashMap<&'static str, String> = HashMap::from([ ("DATETIME", Datetime { date: Some(Date { year: 1979, month: 5, day: 27 } ), time: Some(Time { hour: 7, minute: 32, second: 0, nanosecond: 0 } ), offset: Some(Offset::Z) }.to_string()), ("FIELD", "another string".to_string()), ("ONE_BILLION", (1000000000_f64).to_string()), ]); } ```
## Template, debug, deploy `toml_const` generates 3 toml files into your root project directory (located in `.config/` by default). The contents from `*.template.toml` is used as a base, matching keys from `*.debug.toml` **or** `*.deploy.toml` will override the template values. New keys defined in `debug` or `deploy` will be added as well. Setting the top-level key `use=true` will cause `toml_const` to generate code from that particular config file. | debug use | deploy use | file(s) used | | --------- | ---------- | ----------------------------- | | `false` | `false` | template: compilation warning | | `false` | `true` | template + deploy | | `true` | `false` | template + debug | | `true` | `true` | template + deploy |