Read and parse the Cargo.toml manifest file of a Rust crate

Cargo.toml toml

As part of the Rust Digger project I wanted to read the Cargo.toml file that comes with the project. At first I tried the read_manifest method of the Cargo crate, but I could not figure out how to use it.

Luckily then I encountered the cargo_toml crate that provides a much easier way to get started.

Dependencies

examples/read-cargo-toml/Cargo.toml

[package]
name = "read-cargo-toml"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cargo_toml = "0.19.2"

The code:

examples/read-cargo-toml/src/main.rs

use cargo_toml::{Edition, Manifest};

fn main() {
    for filename in vec![
        "Cargo_only_edition.toml",
        "Cargo_only_version.toml",
        "Cargo_both_edition_and_version.toml",
        "Cargo_neither.toml",
    ] {
        println!("{filename}");

        let manifest = std::fs::read_to_string(filename).unwrap();
        let cargo_toml = Manifest::from_str(&manifest).unwrap();

        //println!("{cargo_toml:?}");
        match cargo_toml.package().rust_version() {
            Some(rust_version) => println!("{rust_version}"),
            None => println!("No rust-version"),
        }

        let edition = cargo_toml.package().edition();
        let year = match edition {
            Edition::E2015 => "2015",
            Edition::E2018 => "2018",
            Edition::E2021 => "2021",
        };
        println!("edition {year}");

        println!("------");
    }

    let filename = "Cargo_invalid_field.toml";

    let manifest = std::fs::read_to_string(filename).unwrap();
    let cargo_toml = Manifest::from_str(&manifest).unwrap();
    println!("{:#?}", cargo_toml);
}

My current interests are the edition and the rust-version fields as I am working on the issue of MSRV (Minimum Supported Rust Version) indication.

Two observations:

  • The Edition field will default to 2015.

  • IF there are invalid fields they are disregarded.

The various sample input files:

examples/read-cargo-toml/Cargo_only_edition.toml

[package]
name = "read-cargo-toml"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cargo_toml = "0.19.2"

examples/read-cargo-toml/Cargo_only_version.toml

[package]
name = "read-cargo-toml"
version = "0.1.0"
rust-version = "1.77"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cargo_toml = "0.19.2"

examples/read-cargo-toml/Cargo_both_edition_and_version.toml

[package]
name = "read-cargo-toml"
version = "0.1.0"
edition = "2021"
rust-version = "1.77"
invalid-field = "invalid value"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cargo_toml = "0.19.2"

examples/read-cargo-toml/Cargo_neither.toml

[package]
name = "read-cargo-toml"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cargo_toml = "0.19.2"

examples/read-cargo-toml/Cargo_invalid_field.toml

[package]
name = "read-cargo-toml"
version = "0.1.0"
edition = "2021"
invalid_field = "invalid value"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cargo_toml = "0.19.2"

The output:

Cargo_only_edition.toml
No rust-version
edition 2021
------
Cargo_only_version.toml
1.77
edition 2015
------
Cargo_both_edition_and_version.toml
1.77
edition 2021
------
Cargo_neither.toml
No rust-version
edition 2015
------

Manifest {
    package: Some(
        Package {
            name: "read-cargo-toml",
            edition: Set(
                E2021,
            ),
            rust_version: None,
            version: Set(
                "0.1.0",
            ),
            build: None,
            workspace: None,
            authors: Set(
                [],
            ),
            links: None,
            description: None,
            homepage: None,
            documentation: None,
            readme: Set(
                Flag(
                    true,
                ),
            ),
            keywords: Set(
                [],
            ),
            categories: Set(
                [],
            ),
            exclude: Set(
                [],
            ),
            include: Set(
                [],
            ),
            license: None,
            license_file: None,
            repository: None,
            default_run: None,
            autobins: true,
            autoexamples: true,
            autotests: true,
            autobenches: true,
            publish: Set(
                Flag(
                    true,
                ),
            ),
            resolver: None,
            metadata: None,
        },
    ),
    workspace: None,
    dependencies: {
        "cargo_toml": Simple(
            "0.19.2",
        ),
    },
    dev_dependencies: {},
    build_dependencies: {},
    target: {},
    features: {},
    replace: {},
    patch: {},
    lib: None,
    profile: Profiles {
        release: None,
        dev: None,
        test: None,
        bench: None,
        doc: None,
        custom: {},
    },
    badges: Badges {
        appveyor: None,
        circle_ci: None,
        gitlab: None,
        travis_ci: None,
        codecov: None,
        coveralls: None,
        is_it_maintained_issue_resolution: None,
        is_it_maintained_open_issues: None,
        maintenance: Maintenance {
            status: None,
        },
    },
    bin: [],
    bench: [],
    test: [],
    example: [],
    lints: None,
}

Related Pages

Toml

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo