Statically include TOML files.
This crate provides a simple way to statically embed data from TOML files at
compile time. The provided macro [`static_toml!`] generates the necessary
data types to represent the TOML data and assigns the parsed TOML data to a
static variable.
# Usage
Including a TOML file is simple.
Here's how to include some text messages defined in a toml:
```toml
# messages.toml
[info]
welcome = "Welcome to our application!"
update = "Your data has been updated successfully."
[errors]
file_not_found = "The requested file could not be found."
permission_denied = "You do not have permission to perform this action."
```
```rust
static_toml::static_toml! {
static MESSAGES = include_toml!("messages.toml");
}
fn main() {
// print the message from the toml file
println!("{}", MESSAGES.info.welcome);
}
```
Accessing the values of nested data structures is done using the dot
notation. IDEs capable of expanding proc macros
(e.g. VS Code with rust-analyzer or CLion with the Rust plugin)
should be able to provide code completion of the included TOML file.
Using `cargo doc` on the crate this macro is called will also generate
enough documentation to inspect the generated data types.
# Syntax
The syntax is designed to be intuitive:
```rust,ignore
static_toml::static_toml! {
[pub] static NAME_1 = include_toml!("file_1.toml");
[pub] static NAME_2 = include_toml!("file_2.toml");
...
[pub] static NAME_N = include_toml!("file_n.toml");
}
```
*Note*:
Although this syntax looks like a typical static value assignment via
`include_*!`, the data type is omitted.
Instead, the data type is generated by the [`static_toml!`] macro call.
The `include_toml!` macro is part of the `static_toml!` macro and does not
need to be imported separately.
In addition to `pub`, other visibilities may also be used.
The passed visibility will automatically be applied to both the root module
of the generated data types and the static value.
For possible values, check
[**Visibility and Privacy** in The Rust Reference](https://doc.rust-lang.org/stable/reference/visibility-and-privacy.html).
Attributes (including doc comments) are also supported:
```
static_toml::static_toml! {
/// doc comments are supported
#[allow(missing_docs)]
#[derive(Debug)]
static EXAMPLE = include_toml!("example.toml");
}
```
The macro attaches doc comments to the generated static value.
Derive attributes are propagated through every constructed data type,
allowing derive macros like [`Default`] to be used. Other attributes are
attached to the root module containing the entry point of the generated data
types.
# Arrays
Arrays in TOML files can have different data types for each item.
However, Rust's slices require all elements to be of the same type.
This crate aims to simplify access to TOML data, so it avoids using
[`Option`] types to handle arrays.
The macro analyzes whether all items in an array have *exactly* the same
data type. If this is the case, it will generate a fixed-sized slice of that
data type, allowing you to iterate over the array and access elements using
the `[n]` syntax.
If the items in the array do not all have the same data type, the macro will
generate a tuple instead.
This allows each position in the tuple to have a different data type.
In cases where at least one item doesn't match the data type structure of
the others, a tuple will be generated.
You can still index such a type easily, as tuples may be directly indexed
via `.n`.
# Configuration
You can configure the [`static_toml!`] macro call by applying a
`static_toml` attribute to the items you want to configure.
- `#[static_toml(prefix = Prefix)]`
The macro will add the specified prefix to the beginning of each generated
data type.
The prefix should be a valid Rust identifier.
- `#[static_toml(suffix = Suffix)]`
The macro will add the specified suffix to the end of each generated data
type.
- `#[static_toml(root_mod = toml)]`
Identifier of the root module that will contain the datatypes for the TOML
file.
If this is not set the name of the static value will be converted to
`snake_case` and used a root mod name.
- `#[static_toml(values_ident = values)]`
When generating the value types for arrays, they need their own namespace.
By default, this macro will use `values` for naming the modules and data
types.
- `#[static_toml(prefer_slices = true)]`
This setting determines whether the macro should try to generate fixed
size slices when working with arrays.
If the setting is set to `false`, the macro will generate tuples for
every array.
By default, this is set to `true`.
- `#[static_toml(auto_doc = true)]`
By default, the macro generates documentation comments, including the file
location and contents, enhancing visibility in the generated docs.
Setting `auto_doc` to `true` ensures auto-generated documentation is appended
after any existing manual comments.
Conversely, setting it to `false` disables automatic documentation generation,
which may result in the static item lacking documentation comments.
This feature is particularly useful for easily accessing TOML contents within
rustdoc.
You can combine attributes as follows:
```rust
static_toml::static_toml! {
// all data types will be prefixed, suffixed and derive Default
#[derive(Default)]
#[static_toml(prefix = Prefix, suffix = Suffix)]
static EXAMPLE = include_toml!("example.toml");
}
```
# Using `const`
While the `static_toml!` macro is named for its primary functionality of
statically including TOML files as `static` variables, it also supports the use
of `const` variables.
This option is provided to accommodate specific use cases where `const` is
necessary.
The use of `const` can be crucial in scenarios such as const functions, which
can refer to `const` variables but not to `static` variables, and const generics
that require `const` values.
When deciding between `static` and `const`, it's important to consider the
memory usage implications.
The `static` keyword is ideal for large TOML files that should only occupy space
in the application once, helping to optimize memory usage.
In contrast, using `const` could potentially increase the binary size,
especially if the same TOML data is reused multiple times.
For further details on the `static` keyword in Rust, see the
[Rust documentation on `static`](https://doc.rust-lang.org/std/keyword.static.html).
To use `const` within the `static_toml!` macro, simply replace `static` with
`const` in the macro call.
For example:
```rust
static_toml::static_toml! {
const MESSAGES = include_toml!("messages.toml");
}
```
It's also possible to mix `static` and `const` entries within the same
`static_toml!` macro call.
However, keep in mind that each identifier must be unique within the same scope.
Here's an example of using both `static` and `const` in a single macro call:
```rust
static_toml::static_toml! {
static MESSAGES = include_toml!("messages.toml");
const EXAMPLE = include_toml!("example.toml");
}
```
# Implementation Details
For the specific details, check the documentation for [`static_toml!`].