A pure rust YAML implementation.

Overview

yaml-rust

The missing YAML 1.2 implementation for Rust.

Travis AppVeyor crates.io docs.rs

yaml-rust is a pure Rust YAML 1.2 implementation, which enjoys the memory safety property and other benefits from the Rust language. The parser is heavily influenced by libyaml and yaml-cpp.

Quick Start

Add the following to the Cargo.toml of your project:

[dependencies]
yaml-rust = "0.4"

and import:

extern crate yaml_rust;

Use yaml::YamlLoader to load the YAML documents and access it as Vec/HashMap:

extern crate yaml_rust;
use yaml_rust::{YamlLoader, YamlEmitter};

fn main() {
    let s =
"
foo:
    - list1
    - list2
bar:
    - 1
    - 2.0
";
    let docs = YamlLoader::load_from_str(s).unwrap();

    // Multi document support, doc is a yaml::Yaml
    let doc = &docs[0];

    // Debug support
    println!("{:?}", doc);

    // Index access for map & array
    assert_eq!(doc["foo"][0].as_str().unwrap(), "list1");
    assert_eq!(doc["bar"][1].as_f64().unwrap(), 2.0);

    // Chained key/array access is checked and won't panic,
    // return BadValue if they are not exist.
    assert!(doc["INVALID_KEY"][100].is_badvalue());

    // Dump the YAML object
    let mut out_str = String::new();
    {
        let mut emitter = YamlEmitter::new(&mut out_str);
        emitter.dump(doc).unwrap(); // dump the YAML object to a String
    }
    println!("{}", out_str);
}

Note that yaml_rust::Yaml implements Index<&'a str> & Index<usize>:

  • Index<usize> assumes the container is an Array
  • Index<&'a str> assumes the container is a string to value Map
  • otherwise, Yaml::BadValue is returned

If your document does not conform to this convention (e.g. map with complex type key), you can use the Yaml::as_XXX family API to access your documents.

Features

  • Pure Rust
  • Ruby-like Array/Hash access API
  • Low-level YAML events emission

Specification Compliance

This implementation aims to provide YAML parser fully compatible with the YAML 1.2 specification. The parser can correctly parse almost all examples in the specification, except for the following known bugs:

  • Empty plain scalar in certain contexts

However, the widely used library libyaml also fails to parse these examples, so it may not be a huge problem for most users.

Goals

  • Encoder
  • Tag directive
  • Alias while deserialization

Minimum Rust version policy

This crate's minimum supported rustc version is 1.31 (released with Rust 2018, after v0.4.3), as this is the currently known minimum version for regex as well.

License

Licensed under either of

at your option.

Contribution

Fork & PR on Github.

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.

Comments
  • Empty string should be quote

    Empty string should be quote

    Hello. I think I found an issue with my pull request #39: I think that the empty string should be quoted, because otherwise, it will be parsed as a Unit. Thanks.

    opened by antoyo 11
  • Error accessing index

    Error accessing index

    Hi :)

    my example yaml:

    
    0:
        important: true
    
    1:
        important: false
    
    
    
    main:
    pub use modules::config;
    fn main() {
        // TODO add via argument
        static CONFIG_STRING: &'static str = "etc/GUS.yml";
        let cfg = config::get_yaml_config(&CONFIG_STRING);
    
        // Let's runtime!
        runtime::RTM { config: &cfg }.run();    
    }
    
    config:
    pub fn get_yaml_config(config_file: &str) -> Array {
        let path_to_file = Path::new(&config_file);
        let display = path_to_file.display();
        let mut fd = match File::open(&path_to_file) {
            Err(why) => panic!("couldn't open {}: {}", display, why.description()),
            Ok(file) => file
        };
    
        let mut content = String::new();
        match fd.read_to_string(&mut content) {
            Err(why) => panic!("couldn't read {}: {}", display, why.description()),
            Ok(_) => println!(""),
        };
        // return Array
        yaml_loader::load_from_str(&content).unwrap()
    }
    
    runtime:
    pub use config;
    use yaml_rust::yaml::Array;
    
    #[derive(Debug)]
    pub struct RTM<'a> {
        pub config: &'a Array
    }
    
    impl<'a> RTM<'a> {
        pub fn run(&self) {
            let gus_config = &self.config[0];
            println!("{:?}", gus_config[0]);
        }
    }
    

    Then get an error when I try to acess index 0:

    thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/option.rs:323
    note: Run with `RUST_BACKTRACE=1` for a backtrace.
    

    Regards Gino

    opened by ThraaxSession 9
  • The feature `preserve_order` is not

    The feature `preserve_order` is not "purely additive," which makes it impossible to use `serde_yaml` 0.5.0 and `clap` in the same program

    Thank you for writing a great YAML parser for Rust! I'm working on several programs which make heavy use of it.

    I ran into a rather tricky problem this morning, when I tried to use two Rust crates in the same program. And I'd love to get your feedback on it:

    • serde_yaml 0.5.0 requires that yaml-rust be configured with the feature preserve_order enabled.
    • clap requires that yaml-rust be configured with preserve_order disabled.

    Trying to use both crates in the same program will turn on preserve_order and break clap:

    error[E0308]: if and else have incompatible types
       --> /home/emk/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-2.18.0/src/args/group.rs:463:30
        |
    463 |         let group_settings = if b.len() == 1 {
        |                              ^ expected struct `linked_hash_map::LinkedHashMap`, found struct `std::collections::BTreeMap`
        |
        = note: expected type `&linked_hash_map::LinkedHashMap<yaml_rust::Yaml, yaml_rust::Yaml>`
        = note:    found type `&'a std::collections::BTreeMap<yaml_rust::Yaml, yaml_rust::Yaml>
    

    I asked the Cargo maintainers on IRC if there was any workaround for this, and they said:

    <sfackler> ekidd: features are normally supposed to be purely additive because of problems like these
    <sfackler> seems like something you'd have to bug the yaml-rust people about unfortunately
    

    As I understand it, this means that if a feature is enabled, it shouldn't change any of the existing APIs of the crate. I'm not sure what the best solution is here.

    I've filed related issues against the affected projects: https://github.com/kbknapp/clap-rs/issues/747 https://github.com/dtolnay/serde-yaml/issues/33

    Thank you for any suggestions you can provide, and for writing a great YAML parser for Rust!

    opened by emk 9
  • Crates.io release is old

    Crates.io release is old

    Hi,

    the latest crates.io release is 8 months old. There're bugfixes (especially in the emitter) that are awesome. It would be great to have a new release with those fixes.

    Thanks

    opened by bomgar 7
  • Arbitrarily-nested hashes/arrays emitted as hash keys

    Arbitrarily-nested hashes/arrays emitted as hash keys

    Cherry-picked from https://github.com/palfrey/yaml-rust/pull/1:

    Currently, heavily nested arrays or hashes used as keys of hashes (such as a hash<hash<array<_>, _>, _>) were either illegally written, or caused an error when attempted to be emitted. This fixes that situation by using the ? ... : YAML mapping form (as shown in example 2.11 here), which is more amenable to writing complex keys.

    If the key of a hashmap is not complex (i.e. a number, string, etc), then the emitting code is unchanged.

    opened by chaaz 7
  • NOT ready for parsing arbitrary user input from untrusted source.

    NOT ready for parsing arbitrary user input from untrusted source.

    Is this still the case, that this library is not ready for accepting untrusted output?

    If so, how much am I risking here? Remote code execution, or a panic? If a panic, that in my application, I could probably live with it, at least temporarily.

    opened by dpc 5
  • Correctly quote all possible booleans.

    Correctly quote all possible booleans.

    Currently, the library incorrectly doesn't add quotes to strings, which will be interpreted as booleans: https://github.com/chyh1990/yaml-rust/blob/bbe06964006ef8c12cd1f08b00bd6a95a0e752d1/src/emitter.rs#L270-L271

    Specs describes many other possiblities: http://yaml.org/type/bool.html

    Personally, I encounter this bug with string TRUE in https://github.com/InQuicker/ktmpl/ which produced such value without qutes and kubernetes doesn't accept that value.

    opened by hrach 5
  • fixed: emitter also emits complex keys

    fixed: emitter also emits complex keys

    Hey, I was playing around with the YamlEmitter and noticed that it did not yet support complex hashmap key and instead returned an Error. With this PR I'm trying to introduce this functionality, please give it a try.

    Thank you very much

    opened by hoodie 5
  • implemented ToString

    implemented ToString

    Hey there, I implemented Yaml::to_string() and From<&Yaml> for String. I know it's a bit of a duplication of YamlEmitter, but I found this more accessible.

    cheers

    opened by hoodie 5
  • alias support

    alias support

    Hey, I just noticed that alias were intended but are not fully implemented. I could use this feature. Could you finish it or perhaps give me some hints so I can do it? Thank you.

    opened by hoodie 5
  • Valgrind complains about uninitialized values

    Valgrind complains about uninitialized values

    I noticed while debugging some Rust apps this crate was throwing uninitialized value warnings in valgrind. I don't know if this is real UB or bogus warnings, just reporting it to be safe.

    Rust version: rustc 1.43.1 (8d69840ab 2020-05-04)

    Test case: https://gist.github.com/xTibor/8858ecf5cbd276bc8673267ee5d324ac

    Valgrind logs:

    ==11197== Conditional jump or move depends on uninitialised value(s)
    ==11197==    at 0x1252C3: yaml_rust::parser::Parser<T>::parser_process_directives (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x1250F3: yaml_rust::parser::Parser<T>::document_start (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x122112: yaml_rust::parser::Parser<T>::next (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x12360A: yaml_rust::parser::Parser<T>::load (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x11E247: yaml_rust::yaml::YamlLoader::load_from_str (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x10D892: overrides::main (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x10D4B2: std::rt::lang_start::{{closure}} (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==    by 0x1362B2: {{closure}} (rt.rs:52)
    ==11197==    by 0x1362B2: std::panicking::try::do_call (panicking.rs:303)
    ==11197==    by 0x137FF6: __rust_maybe_catch_panic (lib.rs:86)
    ==11197==    by 0x136CBB: try<i32,closure-0> (panicking.rs:281)
    ==11197==    by 0x136CBB: catch_unwind<closure-0,i32> (panic.rs:394)
    ==11197==    by 0x136CBB: std::rt::lang_start_internal (rt.rs:51)
    ==11197==    by 0x10DA31: main (in /home/user/git/yaml-rust/target/release/examples/overrides)
    ==11197==  Uninitialised value was created by a stack allocation
    ==11197==    at 0x125250: yaml_rust::parser::Parser<T>::parser_process_directives (in /home/user/git/yaml-rust/target/release/examples/overrides)
    
    opened by xTibor 4
  • Dynamically choosing a YAML document path?

    Dynamically choosing a YAML document path?

    Greetings,

    Thank you for yaml-rust!

    I see in the docs:

    assert_eq!(doc["foo"][0].as_str().unwrap(), "list1");

    I would like to do something like:

    let key = "[foo][0]";
    assert_eq!(doc.dynamic_lookup(key).unwrap(), "list1");
    

    Do you know if it is possible with yaml-rust?

    Thanks!

    opened by mzagrabe 0
  • unsafe-libyaml looks... unsafe?

    unsafe-libyaml looks... unsafe?

    Hi and thanks for this very useful crate.

    I am considering using this crate to use YAML instead of pure JSON for the configuration files of one of my projects, but am not sure what to think about the use of unsafe-libyaml... Safety is a big concern for us and this effectively introduces a bunch of unsafe code responsible for parsing arbitrary input.

    Looking at the history I see that yaml-rust was used previously, but seems to have been abandoned in favor of unsafe-libyaml due to lack of maintenance. That's unfortunate but the decision is understandable.

    Are there other alternatives that could be used to parse YAML? Or are my concerns about unsafe-libyaml unwarranted?

    opened by Gnurou 0
  • Maintainers

    Maintainers

    @chyh1990 Would you like to invite other maintainers to help here or relinquish your cargo publishing area to a developer who would like to step up and maintain the package in their fork?

    opened by hcldan 1
  • Integration with google oss-fuzz fuzzing service

    Integration with google oss-fuzz fuzzing service

    Hi, I would like to help integrate this project into oss-fuzz.

    • As an initial step for integration I have created this PR: https://github.com/google/oss-fuzz/pull/8250, it contains necessary logic from an OSS-Fuzz perspective to integrate yaml-rust. This includes developing initial fuzzers as well as integrating into OSS-Fuzz.

    • Essentially, OSS-Fuzz is a free service run by Google that performs continuous fuzzing of important open source projects.

    • If you would like to integrate, could I please have an email(s), it must be associated with a Google account like gmail (why?). by doing that, the provided email(s) will get access to the data produced by OSS-Fuzz, such as bug reports, coverage reports and more stats.

    • Notice the email(s) affiliated with the project will be public in the OSS-Fuzz repo, as they will be part of a configuration file.

    opened by manunio 0
  • testing: add an integration test for yaml-test-suite

    testing: add an integration test for yaml-test-suite

    The official YAML test suite (https://github.com/yaml/yaml-test-suite). Requires the submodule to be checked out.

    This is a draft PR because there's quite a number of failures. At the moment I'm seeing 62 unexpected errors (and 19 more errors where yaml-rust Event / Parser / EventReceiver API does not provide enough information about the document). I can mark the other errors as expected errors for now, but want to look at them first to check whether they're yaml-rust errors or some mistakes in this test harness.

    opened by tanriol 5
Releases(0.4.4)
Owner
Chen Yuheng
Chen Yuheng
LibYAML bindings for Rust

libyaml-rust LibYAML bindings for Rust Dependencies LibYAML 0.1.4 or higher Stable Rust (2015/2018 edition) Usage Parse from memory extern crate yaml;

김현강 22 Aug 3, 2022
Rust I18n is use Rust codegen for load YAML file storage translations on compile time, and give you a t! macro for simply get translation texts.

Rust I18n Rust I18n is use Rust codegen for load YAML file storage translations on compile time, and give you a t! macro for simply get translation te

Longbridge 73 Dec 27, 2022
Strongly typed YAML library for Rust

Serde YAML This crate is a Rust library for using the Serde serialization framework with data in YAML file format. This library does not reimplement a

David Tolnay 669 Jan 1, 2023
PEG parser for YAML written in Rust 🦀

yaml-peg PEG parser (pest) for YAML written in Rust ?? Quick Start ⚡️ # Run cargo run -- --file example_files/test.yaml # Output { "xmas": "true",

Visarut Phusua 4 Sep 17, 2022
CLI tool to convert HOCON into valid JSON or YAML written in Rust.

{hocon:vert} CLI Tool to convert HOCON into valid JSON or YAML. Under normal circumstances this is mostly not needed because hocon configs are parsed

Mathias Oertel 23 Jan 6, 2023
A cli utility written in Rust that allows fetching all the labels of a project, save those as a YAML file

A cli utility written in Rust that allows fetching all the labels of a project, save those as a YAML file that you can easily edit or save as backup and apply a saved preset to new repositories.

Chevdor 4 May 5, 2022
A Rust library that simplifies YAML serialization and deserialization using Serde.

Serde YML: Seamless YAML Serialization for Rust Serde YML is a Rust library that simplifies YAML serialization and deserialization using Serde. Effort

Sebastien Rousseau 4 Apr 4, 2024
A modern dialogue executor and tree parser using YAML.

A modern dialogue executor and tree parser using YAML. This crate is for building(ex), importing/exporting(ex), and walking(ex) dialogue trees. convo

Spencer Imbleau 27 Aug 3, 2022
A simple CLI for combining json and yaml files

A simple CLI for combining json and yaml files

Avencera 16 Jul 4, 2022
[Proof of Concept] Embedded functional scripting language with YAML ¯\_(ツ)_/¯

[YAML, fun] Just an experimental project implementing embedded functional scripting language based on YAML syntax. API docs for the standard library:

Arijit Basu 12 Aug 15, 2022
YAML(ish) - Terminal UI framework based on templates focused on simplicity

A YAML(ish) based terminal GUI framework for- and by Rust, focussed on making it quick and easy to create a functional UI for an app or game. Based on Crossterm and inspired by Kivy.

null 27 Dec 18, 2022
wireguard tool to manage / generate configuration. Maintain one yaml configuration file to quickly build wireguard network.

wgx wireguard tool to manage / generate configuration. Maintain one yaml configuration file to quickly build wireguard network. Usage wgx --h USAGE:

yinheli 6 Nov 3, 2022
This CLI utility facilitates effortless manipulation and exploration of TOML, YAML, JSON and RON files.

???????? This CLI utility facilitates effortless manipulation and exploration of TOML, YAML, JSON and RON files.

Moe 3 Apr 26, 2023
A yaml-based SQL planner test framework

SQLPlannerTest A yaml-based SQL planner test framework. SQLPlannerTest is a regression test framework. It will read a special yaml file for describing

The RisingLight Project 23 Sep 21, 2022
An Emmet-like language that produces JSON, TOML, or YAML

.august:true August is an Emmet-like language that produces JSON, TOML, or YAML from a single-line concise selector-like syntax. If you aren't familia

Yoav Lavi 39 Aug 17, 2023
Patch binary file using IDA signatures and defined replacement bytes in YAML.

fabricbin Patch binary file using IDA signatures and defined replacement bytes in YAML. Install: cargo install --git https://github.com/makindotcc/fab

makin 3 Oct 24, 2023
A Brotli implementation in pure and safe Rust

Brotli-rs - Brotli decompression in pure, safe Rust Documentation Compression provides a <Read>-struct to wrap a Brotli-compressed stream. A consumer

Thomas Pickert 59 Oct 7, 2022
A (mostly) pure-Rust implementation of various cryptographic algorithms.

Rust-Crypto A (mostly) pure-Rust implementation of various common cryptographic algorithms. Rust-Crypto seeks to create practical, auditable, pure-Rus

null 1.2k Dec 27, 2022
A pure-Rust implementation of group operations on Ristretto and Curve25519

curve25519-dalek A pure-Rust implementation of group operations on Ristretto and Curve25519. curve25519-dalek is a library providing group operations

dalek cryptography 611 Dec 25, 2022
Pure Rust port of CRFsuite: a fast implementation of Conditional Random Fields (CRFs)

crfs-rs Pure Rust port of CRFsuite: a fast implementation of Conditional Random Fields (CRFs) Currently only support prediction, model training is not

messense 24 Nov 23, 2022