taml 0.0.3

A kind-to-humans configuration language.
docs.rs failed to build taml-0.0.3
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.


Lib.rs Crates.io Docs.rs

Rust 1.46.0 Build Status Crates.io - License

GitHub open issues open pull requests crev reviews

TAML is a configuration file format combining some aspects of Markdown, CSV, TOML, YAML and Rust.

As configuration language, TAML's main design goals are to be:

  • Human-writeable
  • Human-readable
  • Unambiguous and Debuggable
  • Computer-readable

Since it is mainly human-oriented and the same data can be represented in multiple ways, there is in fact no serializer in this library. If you need a data transfer format, pretty much anything else will give you better performance.

That said, I believe that for human-written files, TAML offers a great balance between brevity and simplicity, with more than sufficient performance.

A command line validator and formatter is available in the taml-cli crate.
Serde-intergration can be found in serde_taml.


Please use cargo-edit to always add the latest version of this library:

cargo add taml


TODO: Add a good example file here.


Licensed under either of

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Code of Conduct


The grammar

TAML (always UTF-8 where applicable) can represent much of the Serde data model verbatim and is self-describing, as follows:

  • bool is represented as enum with the unit values true and false,

  • all integers are base 10 with optional preceding -.

    • You can (try to) deserialize them as any primitive Rust integer.
    • When deserialized as any, the result is the smallest fitting unsigned or signed integer type.
  • all floats are base 10 with infix . (meaning at least one leading and trailing digit is necessary, each).

    • Deserializing as any results in an f64.
  • char matches Rust: '🦀'

  • byte arrays are unsupported,

  • options are flattened.

    • This means only the Some(_)-variant can be present in seqs.
    • Use #[serde(default)] to parse missing struct keys as None.
  • unit and unit structs are written as empty seq.

  • a unit variant is written as the variant key: Yes

  • newtype structs are flattened,

  • newtype variants are written as key followed by a seq: No("impossible!")

  • seq:

    • either inline (in a single line) similar to Rust tuples:

      ((a, b, c), (d, e)) // seqs can be directly nested this way, but then cannot contain structures.
    • in heading paths:

      # path.with.a.[list].inside
    • or as tabular section:

      # path.to.[[list]]
      # [[vectors].{a, b, c, d}]
      1.0, 2.0, 3.0, 4.0
      1.1, 2.1, 3.1, 4.1
      2.1, 2.2, 3.2, 4.2
      3.1, 3.2, 3.3, 4.3
      4.1, 4.2, 4.3, 4.4
  • tuple and tuple_struct: as seq, but with length validation

  • tuple_variant: as key directly followed by an inline seq, with length validation

  • maps, structs and struct_variants are written as sections containing key-value-pairs (one per line), possibly with subsections.

    • Example:

      # path.to.structure
      key: Value
      `another key`: 1.0
      ## structured_variant:VariantKey
      `nested\`field`: "nested`field"
    • Unlike most Serde formats, TAML by default errors out on unexpected struct or struct_variant fields!

      However, you can collect them in a map by adding a field with the name "taml::extra_fields". Use #[serde(rename = "taml::extra_fields")] or equivalent.

TODO: Describe headings.


taml strictly follows Semantic Versioning 2.0.0 with the following exceptions:

  • The minor version will not reset to 0 on major version changes (except for v1).
    Consider it the global feature level.
  • The patch version will not reset to 0 on major or minor version changes (except for v0.1 and v1).
    Consider it the global patch level.

This includes the Rust version requirement specified above.
Earlier Rust versions may be compatible, but this can change with minor or patch releases.

Which versions are affected by features and patches can be determined from the respective headings in CHANGELOG.md.