Skip to content

jskoiz/saneyaml

Repository files navigation

saneyaml

CI license rust unsafe

Serde-first YAML for Rust — load config straight into your structs with #[derive(Deserialize)], with real YAML 1.2 semantics (so NO stays the string "NO", not false), useful diagnostics, and resource limits built in. Pure Rust, #![forbid(unsafe_code)].

saneyaml feature comparison against serde_yaml, yaml-rust2, and saphyr, plus a real-world config corpus benchmark

Static overview graphic. See source notes and benchmark caveats.

Install

[dependencies]
saneyaml = "0.3.0"

Then use it:

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct Config {
    name: String,
    port: u16,
}

fn main() -> Result<(), saneyaml::Error> {
    let cfg: Config = saneyaml::from_str("name: web\nport: 8080\n")?;
    assert_eq!(cfg.port, 8080);

    let text = saneyaml::to_string(&cfg)?;
    println!("{text}");
    Ok(())
}

Coming from the archived serde_yaml? It's close to a drop-in — see MIGRATION.md.

Why saneyaml

Most Rust YAML libraries make you pick one or the other: serde_yaml's ergonomics (now archived, and YAML 1.1-flavored), or a maintained YAML 1.2 parser like yaml-rust2 or saphyr that hands you a node tree to walk by hand. saneyaml is serde-first and YAML 1.2-correct.

  • Serde-firstfrom_str / from_slice / from_reader, to_string / to_writer, and a serde_yaml-style Value. Deserialize straight into your config structs — no hand-walking a node tree.
  • YAML 1.2 by default — correct scalar resolution, no "Norway problem": NO/on/off/yes stay strings. Opt into YAML 1.1 / serde_yaml-style resolution explicitly via schema modes (Core, Json, Failsafe, LegacySerdeYaml).
  • Diagnostics — line/column, in-document key path (e.g. server.port), and opt-in source-caret rendering.
  • Safe on hostile input — unsafe-free, with structural resource limits: input-size, alias-expansion, nesting-depth, scalar-length, and collection-size controls. Reader-backed entrypoints fully buffer bounded input, and these limits are not wall-clock or resident-memory guarantees.
  • Streaming and source-preserving edits — pull-based event/document iterators that bound retained parsed documents while source bytes remain buffered, plus edit(...) for path-based config refactors that keep comments, anchors, ordering, and untouched bytes.
  • Benchmarked — real-world config corpus runs are tracked against serde_yaml, yaml-rust2, and saphyr; see BENCHMARKS.md.

Status

Pre-1.0 (0.3.0), MSRV Rust 1.88, and actively maintained. The public API is a preview surface but is treated as SemVer-visible: breaking changes and MSRV bumps are explicit, documented release decisions. The road to 1.0 is about locking the surface down, not expanding it — stability is the goal.

Documentation

Start with the Guide, or read the same files in-repo: Getting started and the Cookbook. The docs index maps everything else.

License

MIT — see LICENSE.md.

About

Sane, safe, serde-first YAML for Rust: YAML 1.2 by default, explicit schema modes, real diagnostics, unsafe-free.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages