6.2 KiB
PureYAML Usage
PureYAML is a dependency-free Swift package for parsing, emitting, validating, and typed-converting the YAML subset currently covered by the test corpus.
Installation
The first release target is 0.1.0. After the tag is published, depend on the tagged package version:
.package(url: "https://github.com/mihaelamj/PureYAML.git", .upToNextMinor(from: "0.1.0"))
Until that tag exists, use the main branch:
.package(url: "https://github.com/mihaelamj/PureYAML.git", branch: "main")
Add the product to the target that reads or writes YAML:
.product(name: "PureYAML", package: "PureYAML")
Then import the library:
import PureYAML
Package.swift for PureYAML itself keeps dependencies: []. Consumers do not
need C libraries, generated parser files, JavaScript tooling, or Foundation-only
support code to use the library target.
Public Entry Points
The README examples are mirrored in Tests/DocumentationExampleTests.swift.
Those tests are the executable contract for the short-form examples.
| Need | API | Result |
|---|---|---|
| Parse YAML into an ordered value tree | PureYAML.parse(_:) |
PureYAML.Model.Value |
| Parse a YAML stream into indexed documents | PureYAML.parseStream(_:) |
[PureYAML.Stream.Document] |
| Emit YAML from a value tree | PureYAML.dump(_:options:) |
String |
| Validate a value tree | PureYAML.validate(_:using:strict:) |
[PureYAML.Validation.Issue] or a thrown issue collection |
| Validate stream documents | PureYAML.validate(_:using:strict:) with [PureYAML.Stream.Document] |
[PureYAML.Stream.Issue] or a thrown stream issue collection |
| Decode a typed value from YAML | PureYAML.decode(_:from:) |
Decodable value |
| Encode a typed value to a value tree | PureYAML.encode(_:) |
PureYAML.Model.Value |
| Encode a typed value to YAML | PureYAML.encodeToYAML(_:options:) |
String |
PureYAML intentionally does not expose arbitrary Any dictionary-and-array load
or dump APIs. Use Model.Value for unknown schemas and typed Codable for
known schemas.
Model Usage
Use PureYAML.Model.Value when the caller needs to inspect YAML structure,
preserve mapping order, validate duplicate keys, or handle YAML that does not map
cleanly to a Swift Codable type.
The model currently represents:
null- booleans
- integers
- doubles
- strings
- ordered mappings
- sequences
Mappings preserve insertion order and retain duplicate keys. That is deliberate: validation can report duplicate-key diagnostics instead of losing information by collapsing a mapping into a Swift dictionary too early.
Use PureYAML.parseStream(_:) when an input can contain multiple YAML
documents. The result is an array of PureYAML.Stream.Document values:
let documents = try PureYAML.parseStream("""
---
title: First
---
- Swift
- YAML
""")
PureYAML.parse(_:) remains the single-document API. It accepts one implicit or
explicit document, including an explicit empty document, and throws
unsupportedMultiDocumentStream when a second document is present.
Merge keys are expanded during parsing. Plain << and explicit !!merge keys
inherit mapping entries from a mapping or sequence of mappings; local keys
override inherited keys, and duplicate local keys remain visible to validation.
Quoted "<<": and explicitly string-tagged !!str << keys remain ordinary
string keys.
If a caller needs a JSON-like dictionary after validation, build that projection in application code after deciding how duplicate keys, unsupported tags, and complex keys should behave. Keeping that step outside PureYAML makes the lossy boundary explicit.
Typed Conversion
Use typed conversion when the YAML shape is already known. Current coverage includes:
- scalar
DecodableandEncodablevalues; - keyed mapping-backed structs;
- optional scalar fields;
- nested keyed structs;
- unkeyed sequences;
- nested sequences;
- keyed structs with sequence properties;
- dictionary-like string-keyed mappings where YAML semantics allow them;
- keyed super coders and default
supercoders.
Typed decoding runs the default validator first. Duplicate mapping keys are
reported before Swift Decodable construction starts.
Emitting Options
The default dumper emits deterministic block-style YAML with quoted strings. Callers can opt into:
- conservative plain strings with
.plainWhenSafe; - safe literal block scalars for multiline strings with
.literalBlockWhenMultiline; - compact flow collections with
collectionStyle: .flow.
Literal block emission is conservative. If a multiline string would not round-trip through the current parser, the dumper keeps it as a quoted scalar.
Validation
The default validator rejects duplicate mapping keys anywhere in the value tree. Validation issues include:
- severity;
- reason;
- path.
Strict validation treats warnings as failures. Non-strict validation returns warnings but still throws when errors are present.
Use PureYAML.Validation.Validator.blank when the caller wants only
project-specific validation rules.
Stream validation preserves document indexes without changing document-local paths:
let documents = try PureYAML.parseStream("""
---
title: First
title: Second
---
routes:
- name: Users
name: People
""")
do {
try PureYAML.validate(documents)
} catch let collection as PureYAML.Stream.Issue.Collection {
print(collection.description)
}
The issue descriptions include document[0], document[1], and so on, while
the nested validation path still describes the location inside that document.
Cross-Platform Verification
Before relying on a migration, run the same gates used by the repository:
bash scripts/check-all.sh
bash scripts/check-linux.sh
bash scripts/check-wasm.sh
scripts/check-all.sh includes style, namespacing, forbidden-pattern,
changelog, roadmap, SwiftFormat, SwiftLint, host build, host tests, Linux build
and test, and WASM build checks. The explicit Linux and WASM scripts are useful
when recording release or migration evidence.
Support Boundaries
PureYAML is not yet a complete YAML 1.2 implementation. Before replacing another YAML stack, read MIGRATION.md and compare your input corpus with the supported and unsupported behavior listed there.