fyaml
A safe Rust wrapper around the libfyaml C library for parsing and
manipulating YAML documents.
Overview
fyaml provides an idiomatic Rust interface to the high-performance
libfyaml YAML parsing library. It supports DOM-style navigation,
node type introspection, multi-document parsing, and a serde-compatible
Value type for easy YAML manipulation.
Status
Early development - This library is functional but has not yet been
widely used or audited. The API may change, and edge cases may exist.
If you need a mature, battle-tested YAML library, consider serde_yml
or serde-yaml-ng instead.
Why libfyaml?
fyaml is built on libfyaml, a modern C library that offers
several advantages over the traditional libyaml:
- Full YAML 1.2 compliance with YAML 1.3 preparation
- Zero-copy architecture for efficient large document handling
- No artificial limits (libyaml has a 1024-char implicit key limit)
- Up to 24x faster on large files in streaming mode
- Rich manipulation APIs including YPATH expressions for path queries
- MIT licensed (as of v0.9.1)
This makes fyaml suitable for use cases requiring DOM manipulation,
YAML transformation tools, or configuration inspection utilities where
path-based queries are convenient.
Features
- Parse YAML strings into document objects
- Navigate nodes using path-based queries (e.g.,
/foo/bar,/list/0) - Support for all YAML node types: scalars, sequences, and mappings
- Iterate over mapping key-value pairs and sequence items
- Convert nodes back to YAML strings
- Multi-document stream parsing
- Read YAML from stdin
Valuetype: Pure Rust enum with serde support- Serialize/deserialize with any serde-compatible format (JSON, TOML, etc.)
- Emit YAML using libfyaml for standards-compliant output
- Convenient indexing:
value["key"],value[0]
Installation
Add to your Cargo.toml:
[]
= { = "path/to/fyaml" }
Requires libfyaml-sys as a sibling dependency.
Usage
Working with Value (recommended)
The Value type provides a convenient, serde-compatible way to work with YAML:
use Value;
// Parse YAML
let value: Value = "name: Alice\nage: 30".parse.unwrap;
// Access values with indexing
assert_eq!;
assert_eq!;
// Emit back to YAML
let yaml = value.to_yaml_string.unwrap;
Serde integration
Value works with any serde-compatible format:
use Value;
let value: Value = "key: value".parse.unwrap;
// Convert to JSON
let json = to_string.unwrap;
assert_eq!;
// Parse from JSON
let from_json: Value = from_str.unwrap;
Low-level Node API
For more control, use the Node API directly:
Parsing a YAML string
use Node;
use FromStr;
let yaml = "foo: bar";
let root = from_str.unwrap;
let node = root.node_by_path.unwrap;
assert_eq!;
Navigating nested structures
use Node;
use FromStr;
let yaml = r#"
database:
host: localhost
port: 5432
users:
- admin
- guest
"#;
let root = from_str.unwrap;
// Access nested mapping
let host = root.node_by_path.unwrap;
assert_eq!;
// Access sequence item by index
let first_user = root.node_by_path.unwrap;
assert_eq!;
Iterating over mappings
use Node;
use FromStr;
let yaml = "a: 1\nb: 2\nc: 3";
let root = from_str.unwrap;
for in root.map_iter
Iterating over sequences
use Node;
use FromStr;
let yaml = "- apple\n- banana\n- cherry";
let root = from_str.unwrap;
for item in root.seq_iter
Parsing multiple documents
use ;
let yaml = "---\ndoc1: value1\n---\ndoc2: value2";
let parser = new;
for doc in parser.doc_iter
Checking node types
use ;
use FromStr;
let yaml = "key: value";
let root = from_str.unwrap;
assert!;
assert_eq!;
let value = root.node_by_path.unwrap;
assert!;
API Reference
Value Types
Value- Pure Rust enum representing any YAML value (recommended)Number- Numeric value:Int(i64),UInt(u64),Float(f64)TaggedValue- Value with an associated YAML tag
Value Methods
| Method | Description |
| parse() | Parse YAML string into Value |
| to_yaml_string() | Emit as YAML string via libfyaml |
| is_null() | Check if value is null |
| is_bool() | Check if value is boolean |
| is_number() | Check if value is numeric |
| is_string() | Check if value is a string |
| is_sequence() | Check if value is a sequence |
| is_mapping() | Check if value is a mapping |
| as_str() | Get as &str if string |
| as_i64() | Get as i64 if numeric |
| as_f64() | Get as f64 if numeric |
| as_bool() | Get as bool if boolean |
| as_sequence() | Get as &[Value] if sequence |
| as_mapping() | Get as &IndexMap if mapping |
| get() | Get value by key from mapping |
| [key] / [idx] | Index into mapping or sequence |
Node Types (low-level API)
Node- Safe wrapper around YAML nodesDocument- Safe wrapper around YAML documentsFyParser- YAML parser (supports strings and stdin)NodeType- Enum:Scalar,Sequence,MappingMappingIterator- Iterator over mapping key-value pairsSequenceIterator- Iterator over sequence items
Node Methods
| Method | Description |
| node_by_path() | Navigate to node by path |
| get_type() | Get the node type |
| is_scalar() | Check if node is a scalar |
| is_mapping() | Check if node is a mapping |
| is_sequence() | Check if node is a sequence |
| to_raw_string() | Get raw scalar value |
| to_string() | Get YAML string representation |
| get_tag() | Get optional YAML tag |
| seq_len() | Get sequence length |
| map_len() | Get mapping length |
| map_iter() | Iterate over mapping entries |
| seq_iter() | Iterate over sequence items |
Dependencies
libc- C library bindingslibfyaml-sys- FFI bindings to libfyamllog- Logging frameworkserde- Serialization frameworkindexmap- Order-preserving map for YAML mappings
Other Rust YAML Libraries
| Library | Engine | Serde | Status | | serde_yaml | unsafe-libyaml (libyaml transpiled to Rust) | Yes | Deprecated (2024-03) | | serde_yml | unsafe-libyaml | Yes | Maintained (fork of serde_yaml) | | serde-yaml-ng | unsafe-libyaml | Yes | Active (migrating to libyaml-safer) | | saphyr | Pure Rust (fork of yaml-rust) | Soon | Active | | yaml-rust2 | Pure Rust (fork of yaml-rust) | No | Active (high MSRV) | | yaml-rust | Pure Rust | No | Unmaintained | | fyaml | libfyaml (C library via FFI) | Yes | Development |
Choosing a Library
-
For serde integration:
fyamlprovides a serde-compatibleValuetype with libfyaml-powered parsing and emission. Alternatives includeserde_ymlorserde-yaml-ng(based on unsafe-libyaml). -
For pure Rust: Use
saphyroryaml-rust2(no C dependencies, easier to audit). -
For DOM manipulation and path queries:
fyamlprovides convenient path-based navigation (/foo/0/bar) via libfyaml's YPATH support, plus aValuetype for programmatic manipulation. -
For maximum performance on large files:
fyamlbenefits from libfyaml's zero-copy architecture and streaming optimizations.
License
See the project repository for license information.