toml_const 0.1.0

Compile-time constants from TOML
Documentation
# toml_const
TOML compile-time constants

## Getting started
Add these in your `Cargo.toml` file:
```toml
build = "build.rs"

[[bin]]
name = "toml_const_gen"
path = "src/toml_const_gen.rs"

[dependencies]
toml = "0.8"
lazy_static = "1.4"
toml_const = { git = "https://github.com/cruzerngz/toml_const.git" }

[build-dependencies]
toml_const = { git = "https://github.com/cruzerngz/toml_const.git" }
# crate not published on crates.io yet!
# toml_const = "0.1"
```

Create a new binary file `src/toml_const_gen.rs` with the following code:
```rust
use std::process::ExitCode;

use toml_const::cli;

fn main() -> ExitCode {
    // use a logging library of your choice
    pretty_env_logger::init();

    cli::run()
}
```

Run the binary. MANIFEST_PATH is the path to your Cargo.toml package manifest:
```sh
# run "cargo run... -- init --help" to see more arguments
cargo run --bin toml_const_gen -- init <MANIFEST_PATH>
```

The binary will create and configure some files.

Create a build script, `build.rs`, in the same directory as Cargo.toml:
```rust
// build.rs code
fn main() {
    toml_const::run();

    // ... rest of your build script
}

```

Your package should now look like this:
```sh
package
├── build.rs
├── Cargo.toml
├── .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
├── generated.rs # generated by build.rs
├── .gitignore
└── src
    ├── main.rs
    └── toml_const_gen.rs
```

The generated file `generated.rs` can now be included into your code:
```rust
include!("../generated.rs") // include in main
```

It is recommended 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 = consts::USE; // the USE const must always be defined
```

## Usage
All valid TOML datatypes are generated as compile-time constants, except for arrays and tables.

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 "`_`".

For example, this:
```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
```

Turns to this:
```rust
// ...imports excluded

/// type: i64
pub const TABLE_INTEGER: i64 = (3_i64);
/// type: f64
pub const TABLE_INNER_ONE_BILLION: f64 = (1000000000_f64);
/// type: &'static str
pub const TABLE_INNER_FIELD: &'static str = "another string";
/// type: Datetime
pub const TABLE_TIME: Datetime = Datetime {
    date: None,
    time: Some(Time {
        hour: 11,
        minute: 20,
        second: 0,
        nanosecond: 0,
    }),
    offset: None,
};
/// type: &'static str
pub const TABLE_FIELD: &'static str = "string";
/// 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),
};
```

Toml key `table.time` is is converted to `TABLE_TIME`.

A nested table value `table.inner.one_billion` is destructured to `TABLE_INNER_ONE_BILLION`.

Additionally, 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` contains the `inner` table
// so it is not a last-level table.
//
// HashMaps and arrays are wrapped in 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()),
]);
```

This might be useful when iterating over unknown key-value pairs during runtime. You do lose type information, though.

### Template, debug, deploy
`toml_const` generates 3 toml files into your root project directory.

The contents from `*.template.toml` is used as a base, matching keys from
`*.debug.toml` **or** `*.deploy.toml` will override the template values.

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 |