Skip to main content

Crate noyalib

Crate noyalib 

Source
Expand description

§noyalib

A YAML 1.2 library for Rust. Pure safe code. Full serde integration.

§Two APIs, one parser

noyalib exposes two complementary surfaces over the same scanner and strictness rules. Pick the one that matches your job:

  • Data bindingfrom_str, to_string, Value, StreamingDeserializer, borrowed::BorrowedValue. Read YAML into typed Rust data, write Rust data back to YAML. The round-trip travels through a Value/struct, so comments, blank lines, and the original whitespace are not preserved. Use this for config loaders, RPC payloads, and the 95% of YAML workloads that just want data.

  • Tooling / automationcst::parse_document, cst::parse_stream, cst::Document. Read YAML into a side-table CST that reproduces the source byte-for-byte, targeted edits via doc.set("path", "fragment") rewrite only the touched span — comments, formatting, and sibling entries are left untouched. Use this when what the user wrote matters (Renovate-style version bumps, Kubernetes manifest patchers, formatters, schema-driven linters). See examples/lossless_edit.rs.

§Quick Start

use noyalib::{from_str, to_string};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Config {
    name: String,
    port: u16,
    features: Vec<String>,
}

let yaml = "name: myapp\nport: 8080\nfeatures:\n  - auth\n  - api\n";
let config: Config = from_str(yaml).unwrap();
assert_eq!(config.name, "myapp");
assert_eq!(config.port, 8080);

let output = to_string(&config).unwrap();
let roundtrip: Config = from_str(&output).unwrap();
assert_eq!(config, roundtrip);

§Deserialization

// From string, byte slice, reader, or Value
let v: Value = noyalib::from_str(yaml).unwrap();
let v: Value = noyalib::from_slice(bytes).unwrap();
let v: Value = noyalib::from_reader(file).unwrap();
let v: Value = noyalib::from_value(&value).unwrap();

// With security limits
let config = noyalib::ParserConfig::strict();
let v: Value = noyalib::from_str_with_config(yaml, &config).unwrap();

§Serialization

// To string, writer, or fmt::Write
let yaml: String = noyalib::to_string(&value).unwrap();
let mut buf = Vec::new();
noyalib::to_writer(&mut buf, &value).unwrap();
let mut s = String::new();
noyalib::to_fmt_writer(&mut s, &value).unwrap();

// With custom config
let config = noyalib::SerializerConfig::new()
    .indent(4)
    .quote_all(true);
let yaml = noyalib::to_string_with_config(&value, &config).unwrap();

§Highlights

  • Pure Rust — native YAML 1.2 scanner and parser. No C bindings. No FFI.
  • Zero unsafe#![forbid(unsafe_code)] enforced at compile time.
  • Fast — 75% faster serialization, 50% faster deserialization than serde_yaml_ng. Streaming deserializer bypasses the Value AST.
  • Serde-native — serialize and deserialize any Serialize / Deserialize type.
  • Ordered mappingsIndexMap-backed. Insertion order preserved.
  • Source spansSpanned<T> tracks exact line, column, and byte offset.
  • Hardened — configurable depth, size, and alias limits. Billion-laughs safe.
  • 100% YAML Test Suite — 406/406 official test cases pass.
  • Zero-copyborrowed::BorrowedValue borrows strings from input.
  • Path queriesvalue.query("items[*].name") with wildcards.
  • no_std — works with alloc only (default-features = false).
  • miette — optional rich terminal diagnostics (--features miette).

§API stability and SemVer policy

noyalib follows Semantic Versioning 2.0.0. Pre-1.0, the version axis used for breaking changes is the patch number during the 0.0.x series and the minor number during the 0.x.y series — patch bumps within a stable line are source-compatible.

  • Public surface = items reachable from the crate root by an in-scope pub use (this file). Items reachable only via a pub module (e.g. helpers in borrowed, cst, policy) are also public; everything in a pub(crate) / private module is internal.
  • #[non_exhaustive] is applied to every public configuration struct (ParserConfig, SerializerConfig, Error, MergeKeyPolicy, DuplicateKeyPolicy, FlowStyle, ScalarStyle, YamlVersion) so adding a field or variant in a future release is not a breaking change. Construct configuration via the documented new / default / strict constructors plus the builder setters; do not use exhaustive struct-literal syntax outside this crate.
  • What we will not break in patch releases:
    • public function signatures (parameter names, types, return types);
    • the Value enum’s variant set;
    • re-exported macro names (none today);
    • the YAML 1.2 default-strictness contract.
  • The deserialise-target bound is T: for<'de> Deserialize<'de> + 'static. The 'static half is the contract every real-world DeserializeOwned type already satisfies (the HRTB itself disallows borrowed lifetimes); it is documented explicitly because a small number of externally-defined trait signatures (e.g. figment’s Format::from_str) drop the 'static from their own bound — for those, noyalib provides feature-gated internal entry points that bypass the Value-tag-preserving fast path.
  • What may change without a major bump: non-default ParserConfig semantics under explicit opt-in (e.g. a future legacy_* flag), error message wording (variant names are stable), benchmark numbers, internal module layout.
  • Deprecations ship with #[deprecated(since = "x.y.z", note = "...")] for at least one minor release before removal. CHANGELOG carries the migration recipe.
  • API drift checks: cargo semver-checks runs in CI on every PR.

§MSRV policy

  • Core library (noyalib) — Rust 1.75.0 stable. CI’s msrv-1-75-core job builds the default-features = false and the standard default set on rustc 1.75.0 for every PR. The MSRV is treated as part of the public contract: a bump within 0.0.x is a breaking change and ships a major version.
  • Optional features that pull a dep with a higher floor (miette, garde, validate-schema, figment, parallel, validator) inherit that dep’s MSRV — currently 1.801.86 depending on the feature. The CI matrix runs each one against the dep’s declared rust-version.
  • Companion crates (noya-cli, noyalib-lsp) carry their own higher MSRVs because their dep tree includes edition-2024 transitives — 1.85.0 for both at time of writing.
  • nightly-simd is the only feature that requires nightly rustc (#![feature(portable_simd)]); a build.rs cfg-detect probe means stable builds with --all-features still compile by treating nightly-simd as a no-op.

§Feature flag matrix

All optional integrations are off by default — enable only what your application needs. Default-on flags can be opted out via default-features = false.

FeatureDefaultPulls inAddsImplies
stdI/O, Spanned<T> deserialise, cst
fast-intitoabranchless integer formattingstd recommended
fast-floatryubranchless float formattingstd recommended
strict-deserialiseserde_ignoredfrom_*_strict familystd
minimalmeta-alias for std only (drops the three above)std
miettemiette 7rich terminal diagnostics
schemaschemars, serde_jsonschema_for / schema_for_yaml + consumer must also depend on schemars = "1.2" to derive JsonSchema
validate-schemaschema + jsonschemavalidate_against_schema, coerce_to_schemaschema
figmentfigment 0.10figment::Yaml Providerstd
gardegarde 0.22Validated<T>
validatorvalidator 0.19ValidatedValidator<T>
roboticsDegrees / Radians / StrictFloat newtypes
parallelrayon 1.10parallel::parse, parallel::valuesstd
simdnoyalib::simd::* primitives
nightly-simdnightly rustc32-byte StructuralItersimd
compat-serde-yamlnoyalib::compat::serde_yaml shim
compare-saphyrserde-saphyrcomparison-bench arms (dev-only — do not ship in release builds)
noyavalidatemeta-feature: validate-schema + miettevalidate-schema, miette
wasm-optmarker consumed by noyalib-wasm’s build.rs to opt into a Binaryen post-build pass

docs.rs builds with --all-features; every gated item is tagged with the feature it requires via the doc(cfg(...)) badge.

§Concurrency guarantees

  • All public top-level functions (from_str, from_slice, from_reader, to_string, to_writer, …) are pure over their inputs and may be called concurrently from any number of threads.
  • Value, Mapping, Number, Spanned<T>, Error are Send + Sync. Cloning a Value is O(n) in the value graph; share ownership via Arc<Value> when that cost matters.
  • policy::Policy requires Send + Sync so policies can be shared by reference across threads. Stateful policies should hold their state behind interior mutability (std::sync::Mutex or equivalent).
  • Spanned<T> deserialisation uses a thread-local span context (std feature). The TLS guard installs on entry to from_str_with_config and clears on return — no leakage across calls or across threads.
  • Anchor and alias state lives in the parser stack frame (one per call); concurrent calls share no mutable state.
  • The Rayon-backed parallel module pre-scans document boundaries on the calling thread, then dispatches each document to the global Rayon pool — T: Send is required.
  • anchors::ArcAnchorRegistry / anchors::ArcAnchor use Arc + Weak and are explicitly multi-thread-safe; the Rc-backed siblings are single-thread.

§Security posture

  • No unsafe#![forbid(unsafe_code)] enforced at compile time on every workspace crate.
  • No FFI — pure Rust scanner / parser / serialiser / CST. Closes the historical libyaml C-FFI CVE class.
  • No arbitrary object instantiation from tags — custom tags surface as Value::Tagged data; opt-in dispatch via TagRegistry. There is no path from a parsed YAML document to running attacker-chosen code.
  • Resource budgets — seven configurable limits in ParserConfig cap depth, document size, alias expansions, mapping keys, sequence length, duplicate-key policy, and boolean strictness. ParserConfig::strict tightens every budget for untrusted input. Alias-byte accumulation uses saturating_add so a crafted overflow still trips the cap.
  • Pluggable policiespolicy::DenyAnchors, policy::DenyTags, policy::MaxScalarLength for organisational “Safe YAML” enforcement. Custom policies implement policy::Policy.
  • Supply chaincargo audit, cargo deny, cargo vet gate every PR. Releases ship SLSA L3 provenance and sigstore signatures (verification cookbook in pkg/VERIFY.md). No archived or unmaintained crate appears in the dependency graph.

Disclosure policy: see SECURITY.md.

§Performance and complexity

  • Parser — single-pass, O(n) in input bytes for the scanner; loader is O(n) events. IndexMap insert is amortised O(1); FxHasher keeps key hashing cheap on short keys.
  • Streaming deserialise — bypasses the dynamic Value AST when the caller asks for a typed T, eliminating intermediate allocations. ~30% faster than the AST-via-Value path on real workloads.
  • Zero-copy scanner — string scalars come out as Cow::Borrowed when no escape sequence forces an allocation. borrowed::BorrowedValue surfaces this all the way to the caller.
  • SIMD primitivessimd::find_any_of dispatches to memchr SSE2/NEON for arity 1/2/3 and SWAR for arity 4+. With nightly-simd, the structural-bitmask scanner widens to 32-byte lanes — ~9× speedup vs the memchr loop on 1 MiB inputs.
  • SWAR decimal parser — folds 8 ASCII digits per u64 cycle. ~2× faster than <i64 as FromStr>::from_str on big numbers.
  • Serialiser — branchless integer (itoa) and float (ryu) formatting in the hot path; falls back to core::fmt under --no-default-features.
  • Parallel multi-documentparallel::parse scales near-linearly with cores on ----separated streams; the pre-scan is O(input.len()) on the calling thread.
  • Value::clone is O(n) over the value graph; share via Arc<Value> when that matters.

§Platform support

  • Tier 1: x86_64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin, x86_64-pc-windows-msvc, aarch64-unknown-linux-gnu. CI runs on each of these on every PR.
  • Tier 2: musl Linux (*-musl), i686-pc-windows-msvc, aarch64-pc-windows-msvc. Built in release CI; not gated on every PR.
  • Embedded / no_std: any target supported by alloc. The std-only items (from_reader, to_writer, Spanned<T> deserialisation via TLS, the cst module) are gone; the rest of the surface compiles. CI enforces cargo check --no-default-features on every PR.
  • WASM: wasm32-unknown-unknown via the noyalib-wasm companion crate. 338 KB release binary (LTO). Browser demo in crates/noyalib/examples/wasm/.
  • Big-endian: validated under Miri’s mips64-unknown-linux-gnuabi64 simulation in the weekly miri-bigendian job.

§Error model

Every fallible function returns Result<T> aliasing core::result::Result<T, Error>. Error is #[non_exhaustive], implements core::fmt::Display, core::error::Error (via std::error::Error under the std feature), and — with --features miettemiette::Diagnostic for rich terminal reports.

Each entry-point’s # Errors section enumerates the variant set callers must handle; cross-reference the Error variants for descriptions.

Re-exports§

pub use document::DocumentReadIterator;std
pub use document::read;std
pub use document::read_with_config;std
pub use document::load_all;
pub use document::load_all_as;
pub use document::load_all_with_config;
pub use document::try_load_all;
pub use fmt::Commented;
pub use fmt::FlowMap;
pub use fmt::FlowSeq;
pub use fmt::FoldStr;
pub use fmt::FoldString;
pub use fmt::LitStr;
pub use fmt::LitString;
pub use fmt::SpaceAfter;
pub use tag_registry::TagRegistry;
pub use validated::Validated;garde
pub use validated::ValidatedValidator;validator

Modules§

ariadne_adapterariadne
Zero-copy YAML values that borrow from the input. ariadne adapter — render crate::Error as an ariadne::Report with the offending byte range labelled. Behind the ariadne Cargo feature. ariadne adapter for crate::Error.
borrowed
Zero-copy YAML values that borrow strings from the input.
compat
Drop-in compatibility shims for upstream YAML crates. Each shim is gated behind its own feature flag so unused migration paths add zero compile cost. See compat::serde_yaml for the serde_yaml 0.9 surface. Compatibility shims for downstream crates migrating to noyalib.
cststd
Side-table CST for byte-faithful round-tripping with typed path-targeted edits.
diagnosticmiette
Spanned-to-miette diagnostic bridge (requires miette feature). Spanned value to miette::Report bridge.
document
Multi-document loading and iteration. Multi-document YAML loading.
figmentfigment
figment provider integration. Pulls in figment 0.10 when the figment Cargo feature is enabled. figment provider for noyalib YAML.
fmt
Formatting wrappers for per-value YAML output style control. Formatting wrappers for fine-grained control over YAML output style.
i18n
Pluggable error-message formatters: i18n::MessageFormatter trait plus i18n::DefaultFormatter (developer-facing, verbatim) and i18n::UserFormatter (user-facing, simplified language). Use crate::Error::render_with_formatter to plug in localisation tables or custom rendering. Pluggable error-message formatters for user-facing rendering.
includeinclude
!include directive — resolver types (IncludeResolver, IncludeRequest, InputSource, SymlinkPolicy, SafeFileResolver). Wired into ParserConfig::include_resolver. !include directive support — compose YAML documents from multiple files via the !include path/to/file.yaml tag.
interner
Key interning for memory-efficient repeated-key workloads. Key interning for memory-efficient repeated-key workloads.
parallelparallel
Parallel multi-document YAML parsing via Rayon. Gated by the parallel feature. Parallel multi-document YAML parsing — the “MapReduce” path.
policy
Pluggable parser policies for “Safe YAML” enforcement. Pluggable parser policies for “Safe YAML” enforcement.
roboticsrobotics
Robotics and scientific numeric types (requires robotics feature). Robotics and scientific numeric types for precise YAML deserialization.
simd
SIMD-friendly multi-byte search primitives.
tag_registry
Streaming-path registry for custom YAML tag pass-through.
validatedgarde or validator
Declarative post-deserialise validation via garde or validator (requires the corresponding feature). Declarative validation via garde or validator.
validated_miettemiette
Spanned<T> + garde / validator → miette::Report bridge. Behind the miette Cargo feature; the actual conversion functions are gated on miette + garde or miette + validator. Spanned<T> + garde / validatormiette::Report bridge.
with
Helper modules for customizing serialization and deserialization.

Macros§

parser_config
Construct a crate::ParserConfig from a field-value list.
serializer_config
Construct a crate::SerializerConfig from a field-value list.

Structs§

AnchorRegistry
Registry for shared Rc anchor references during deserialization.
ArcAnchor
An Arc wrapper with YAML anchor semantics.
ArcAnchorRegistry
Registry for shared Arc anchor references during deserialization.
ArcRecursionstd
Thread-safe weak recursive reference — pairs with ArcRecursive.
ArcRecursivestd
Thread-safe recursive anchor type — the RcRecursive counterpart for cross-thread / parallel-parse use cases.
ArcWeakAnchor
A weak Arc reference with YAML anchor semantics.
Comment
A scanned YAML comment with its source span and classification.
CroppedRegion
A windowed slice of source text around an error location.
Deserializer
A YAML deserializer.
Flattened
Wrapper that pairs a typed deserialization of T with the underlying Value tree captured from the source.
Location
A (line, column, byte index) location in a YAML document.
Mapping
A YAML mapping (dictionary/object).
MappingAny
A YAML mapping with Value keys.
ParseNumberError
Error returned when parsing a number from a string fails.
ParserConfig
Deserialization configuration.
RcAnchor
An Rc wrapper with YAML anchor semantics.
RcRecursionstd
Single-threaded weak recursive reference — pairs with RcRecursive.
RcRecursivestd
Single-threaded recursive anchor type for cyclic / late-initialised YAML graphs.
RcWeakAnchor
A weak Rc reference with YAML anchor semantics.
RenderOptions
Caller-controlled rendering options for Error::render_with_options.
Serializer
A YAML serializer.
SerializerConfig
Configuration options for YAML serialization.
Spanned
A value annotated with source span information.
StreamingDeserializer
A streaming YAML deserializer operating directly on parser events.
Tag
A YAML tag.
TaggedValue
A tagged YAML value.

Enums§

BudgetBreach
Errors that can occur during YAML serialization or deserialization.
CommentKind
Classification of a scanned comment.
DuplicateKeyPolicy
Policy for handling duplicate keys in a YAML mapping.
Error
Examples
FlowStyle
Flow style preference for collections.
MaybeTag
Result of checking whether a value looks like a YAML tag.
MergeKeyPolicy
Number
Represents a YAML number.
Path
Represents a path to a location within a YAML document structure.
RequireIndent
Policy for handling the YAML merge key (<<) during parsing.
ScalarStyle
Scalar style preference for strings.
Value
Represents any valid YAML value.
YamlVersion
Which version of the YAML specification the resolver follows.

Traits§

JsonSchemaschema
Re-export of the schemars derive macro and trait. Deriving JsonSchema on your Rust type is what makes schema_for / schema_for_yaml produce a schema for it.
ValueIndex
A type that can be used to index into a Value.

Functions§

check_for_tag
Checks whether a value’s display representation looks like a YAML tag.
coerce_to_schemavalidate-schema
Apply schema-driven type coercions to value in place. Walks the validator output for type-mismatch errors, and for each case where the instance is a Value::String but the schema requires an integer / number / boolean — and the string parses cleanly into that target type — replaces the offending node with the coerced value.
from_readerstd
Deserialize YAML from an std::io::Read source.
from_reader_strictstd and strict-deserialise
Strict deserialise from an IO reader — like from_reader but errors if the input contains keys the target type T does not declare.
from_reader_with_configstd
Deserialize YAML from an std::io::Read source with a custom ParserConfig.
from_slice
Deserialize YAML from a byte slice.
from_slice_strictstd and strict-deserialise
Strict deserialise from a byte slice — like from_slice but errors if the input contains keys the target type T does not declare.
from_slice_with_config
Deserialize YAML from a byte slice with a custom ParserConfig.
from_str
Deserialize YAML from a &str into a typed T.
from_str_borrowing
Deserialise a YAML document into a target type that may borrow from the input slice (e.g. &'a str, Cow<'a, str>, structs containing those).
from_str_borrowing_with_config
from_str_borrowing with a custom ParserConfig — typically to tighten security limits for untrusted input.
from_str_strictstd and strict-deserialise
Strict deserialise: like from_str but errors if s contains any keys that the target type T does not declare.
from_str_with_config
Deserialize YAML from a &str with a custom ParserConfig.
from_value
Deserialize a Value into a typed T via Serde’s data model.
is_yaml_failsafe_compatible
Check if a value uses only YAML 1.2 Failsafe schema types.
is_yaml_json_compatible
Check if a value is valid against the YAML 1.2 JSON-compatible schema.
load_comments
Scan a YAML document and return the list of comments it contains.
nobang
Strips a leading ! from a string, if present.
schema_forschema
Generate the JSON Schema 2020-12 document for T and parse it into a crate::Value tree, ready for indexing, transcoding, or further programmatic walking.
schema_for_yamlschema
Generate the JSON Schema 2020-12 document for T and emit it as YAML text — ready to write to disk, share with downstream consumers, or check into version control alongside the type definition.
to_fmt_writer
Serialize a Rust value to YAML and write into a core::fmt::Write sink — the no_std-friendly counterpart to to_writer.
to_fmt_writer_with_config
Serialize a Rust value to YAML and write into a core::fmt::Write sink, using a custom SerializerConfig.
to_string
Serialize a Rust value to a YAML String.
to_string_multi
Serialize an iterable of values as a multi-document YAML string with --- document-start markers between each.
to_string_multi_with_config
Serialize an iterable of values as a multi-document YAML string with a custom SerializerConfig.
to_string_tracking_sharedstd
Serialize a Rust type to a YAML string with automatic anchor/alias emission for shared Rc and Arc pointers wrapped in RcAnchor / ArcAnchor.
to_string_tracking_shared_with_configstd
Serialize with automatic anchor/alias emission and a custom configuration.
to_string_value
Serialize a Value directly to a YAML String, preserving Value::Tagged shape losslessly.
to_string_value_with_config
Serialize a Value to a YAML String with a custom SerializerConfig, preserving Value::Tagged shape losslessly. See to_string_value for the rationale.
to_string_with_config
Serialize a Rust value to a YAML String with a custom SerializerConfig.
to_value
Serialize a Rust value into a dynamic Value tree via the Serde data model.
to_writerstd
Serialize a Rust value to YAML and write to a std::io::Write sink.
to_writer_multistd
Serialize multiple values as multi-document YAML to a writer.
to_writer_multi_with_configstd
Serialize multiple values as multi-document YAML to a writer with custom configuration.
to_writer_tracking_sharedstd
Write YAML to a writer with automatic anchor/alias emission for shared Rc / Arc pointers.
to_writer_tracking_shared_with_configstd
Write YAML to a writer with automatic anchor/alias emission and a custom configuration.
to_writer_valuestd
Write a Value to an std::io::Write sink, preserving Value::Tagged shape losslessly. See to_string_value for the rationale.
to_writer_value_with_configstd
Write a Value to an std::io::Write sink with a custom SerializerConfig, preserving Value::Tagged shape losslessly. See to_string_value for the rationale.
to_writer_with_configstd
Serialize a Rust value to YAML and write to a std::io::Write sink, using a custom SerializerConfig.
validate_against_schemavalidate-schema
Validate value against the JSON Schema 2020-12 document schema. Both inputs are Value trees — the schema is usually loaded from a YAML / JSON file via crate::from_str, or built programmatically.
validate_against_schema_strvalidate-schema
Validate the YAML text in yaml against the JSON Schema document in schema_yaml. Convenience wrapper around validate_against_schema — parses both inputs and forwards.
validate_yaml_core_schema
Validate a value against the YAML 1.2 Core Schema.
validate_yaml_failsafe_schema
Validate a value against the YAML 1.2 Failsafe Schema.
validate_yaml_json_schema
Validate a value against the YAML 1.2 JSON-compatible schema level.

Type Aliases§

Result
A result type where the error is Error.
Sequence
A YAML sequence (array/list).

Derive Macros§

JsonSchemaschema
Re-export of the schemars derive macro and trait. Deriving JsonSchema on your Rust type is what makes schema_for / schema_for_yaml produce a schema for it.