tomling
is a simple TOML parser API, that is designed to have minimal dependencies and is no_std
compatible. The main target is Cargo manifests (Cargo.toml
files) and hence why specific
API is provided for that purpose as well.
use tomling::{
cargo::{BuildDependency, Dependency, Manifest, ResolverVersion, RustEdition},
Value, parse,
};
//
// Using the `Cargo.toml` specific API:
//
let manifest: Manifest = tomling::from_str(CARGO_TOML).unwrap();
assert_eq!(manifest.package().name(), "example");
assert_eq!(manifest.package().version(), "0.1.0");
assert_eq!(manifest.package().edition().unwrap(), RustEdition::E2021);
assert_eq!(manifest.package().resolver().unwrap(), ResolverVersion::V2);
let authors = manifest.package().authors().unwrap();
let alice = &authors[0];
assert_eq!(alice.name(), "Alice Great");
assert_eq!(alice.email(), Some("foo@bar.com"));
let bob = &authors[1];
assert_eq!(bob.name(), "Bob Less");
assert_eq!(bob.email(), None);
let serde = match manifest.dependencies().unwrap().by_name("serde").unwrap() {
Dependency::Full(serde) => serde,
_ => panic!(),
};
assert_eq!(serde.version(), "1.0");
assert_eq!(serde.features(), Some(&["std", "derive"][..]));
let regex = match manifest.dependencies().unwrap().by_name("regex").unwrap() {
Dependency::VersionOnly(regex) => *regex,
_ => panic!(),
};
assert_eq!(regex, "1.5");
let cc = match manifest
.targets()
.unwrap()
.by_name("cfg(unix)")
.unwrap()
.build_dependencies()
.unwrap()
.by_name("cc")
.unwrap()
{
BuildDependency::VersionOnly(cc) => *cc,
_ => panic!(),
};
assert_eq!(cc, "1.0.3");
let default = manifest.features().unwrap().by_name("default").unwrap();
assert_eq!(default, &["serde"]);
let binary = &manifest.binaries().unwrap()[0];
assert_eq!(binary.name(), "some-binary");
assert_eq!(binary.path(), Some("src/bin/my-binary.rs"));
//
// Using the generic raw `TOML` parsing API:
//
let manifest = parse(CARGO_TOML).unwrap();
let package = match manifest.get("package").unwrap() {
Value::Table(package) => package,
_ => panic!(),
};
assert_eq!(package.get("name").unwrap(), &Value::String("example"));
assert_eq!(package.get("version").unwrap(), &Value::String("0.1.0"));
assert_eq!(package.get("edition").unwrap(), &Value::String("2021"));
assert_eq!(package.get("resolver").unwrap(), &Value::String("2"));
let deps = match manifest.get("dependencies").unwrap() {
Value::Table(deps) => deps,
_ => panic!(),
};
let serde = match deps.get("serde").unwrap() {
Value::Table(serde) => serde,
_ => panic!(),
};
assert_eq!(serde.get("version").unwrap(), &Value::String("1.0"));
let serde_features = match serde.get("features").unwrap() {
Value::Array(features) => features.as_slice(),
_ => panic!(),
};
assert_eq!(serde_features, &[Value::String("std"), Value::String("derive")]);
let regex = match deps.get("regex").unwrap() {
Value::String(regex) => *regex,
_ => panic!(),
};
assert_eq!(regex, "1.5");
const CARGO_TOML: &'static str = r#"
[package]
name = "example"
version = "0.1.0"
edition = "2021"
authors = ["Alice Great <foo@bar.com>", "Bob Less"]
resolver = "2"
[dependencies]
serde = { version = "1.0", features = [
"std",
"derive", # and here.
] }
regex = "1.5"
[target.'cfg(unix)'.build-dependencies]
cc = "1.0.3"
[features]
default = ["serde"]
[[bin]]
name = "some-binary"
path = "src/bin/my-binary.rs"
"#;
winnow
with alloc
and simd
features enabled.serde
(optional) with alloc
and derive
features enabled.serde
- Enables Serde support.cargo-toml
- Enables Cargo manifest specific API. This requires serde
.simd
- Enables the simd
feature of winnow
for SIMD acceleration for parsing.std
- Enables some features, like std::error::Error
implementation for Error
type. It also
enables std
feature of winnow
and serde
.All features are enabled by default.
toml
crateThe toml
crate is great but it being based on toml-edit
, it ends up requiring indexmap
crate
and its dependencies. tomling
was created specifically to avoid most of these dependencies by
focusing completely on the parsing of TOML
documents only.
winnow
with only 2 features enabled.The name "tomling" is a portmanteau of "TOML" and "ling" (a suffix meaning "a small thing"). Coincidentally, it also means a "male kitten" in English, with all the stress on the "kitten" part 😸 and none on the "male" part.