PureYAML/docs/MIGRATION.md

6.7 KiB

Migration and YAML Support Boundaries

PureYAML can replace a C-backed YAML parser when the caller needs dependency-free Swift parsing, emitting, validation, and typed conversion for the currently tested YAML subset.

It should not be treated as a drop-in full YAML implementation yet. The current contract is the behavior pinned by the Swift Testing corpus.

Attribution Boundary

PureYAML is informed by the behavior and public API shape of Yams and its bundled CYaml / libyaml-derived parser. The public implementation is original Swift code in this repository. Do not copy Yams, CYaml, or libyaml implementation code into Sources/.

See ../ATTRIBUTION.md for the project attribution.

Migration Map

Existing need PureYAML path Notes
Compose YAML into a native YAML tree PureYAML.parse(_:) Returns PureYAML.Model.Value, preserving mapping order and duplicate keys.
Serialize a YAML tree PureYAML.dump(_:options:) Emits deterministic YAML with explicit block, flow, and scalar policies.
Decode a Decodable type from YAML PureYAML.decode(_:from:) Runs default validation before typed decoding.
Encode an Encodable value to YAML PureYAML.encodeToYAML(_:options:) Encodes through PureYAML.Model.Value, then dumps.
Validate document structure PureYAML.validate(_:using:strict:) Default rule reports duplicate mapping keys with exact paths.
Load arbitrary Any dictionaries and arrays Use Model.Value or typed Codable There is no arbitrary Any conversion API yet.

Supported Today

The supported list below is covered by tests. When adding a new migration case, add a fixture beside the closest existing suite.

Area Current behavior Test coverage
Block mappings and sequences Parsed into ordered mappings and sequences. ParsingTests, CollectionCompatibilityFixtures
Common scalars Null, booleans, integers, doubles, and strings resolve into model values. ParsingTests, ScalarCompatibilityFixtures
Quoted strings Single and double quoted strings keep string intent. ParsingTests, ScalarCompatibilityFixtures
Comments Comments outside quoted strings are ignored. Hash characters inside quoted strings remain content. ParsingTests
Flow collections Flow sequences and flow mappings compose into model values. ParsingTests, CollectionCompatibilityFixtures
Literal and folded blocks Block scalar text is preserved according to current parser rules. ParsingTests, DumperTests
Anchors and aliases Scalar and mapping anchors can be reused through aliases. Undefined aliases throw exact parse errors. ParsingTests, CollectionCompatibilityFixtures
YAML directives and document markers %YAML 1.2, selected %TAG expansion, ---, and ... are supported for single-document streams. ParsingCompatibilityTests
Built-in scalar tags !!str, !!int, !!float, !!bool, and !!null are applied when valid. ScalarCompatibilityFixtures
Emitting Deterministic block output by default, with opt-in flow collections and conservative literal blocks. DumperTests, EmitterCorpusTests
Typed conversion Scalar, keyed, unkeyed, nested, sequence, dynamic-key, and super-coder cases are covered. CodingTests, CodableCompatibilityTests
Validation Duplicate mapping keys are reported with exact issue paths. ValidationTests, ValidationModelTests
Downstream-shaped documents API-style and service-configuration documents parse and decode through representative paths. DownstreamDocumentTests

Current Unsupported Behavior

Unsupported behavior is either rejected with an exact error or preserved as an explicit fallback value tree. This avoids silent compatibility drift.

YAML pattern Current PureYAML behavior Test coverage
Multi-document streams Throws unsupportedMultiDocumentStream. UnsupportedYAMLGapsFixtures.parseErrors
Content after explicit document end Throws unsupportedMultiDocumentStream; trailing comments after ... remain non-content. UnsupportedYAMLGapsFixtures
Complex mapping keys such as ? [a, b] or ? {name: Example} Throws expectedScalarKey. UnsupportedYAMLGapsFixtures.parseErrors
Unknown directives such as %FOO Throws unsupportedDirective. UnsupportedYAMLGapsFixtures.parseErrors
%TAG after content or after document start Throws unsupportedDirective. UnsupportedYAMLGapsFixtures.parseErrors
Undefined aliases Throws undefinedAlias. CollectionCompatibilityFixtures.parseErrors
Invalid explicit scalar tag values Throws invalidTaggedScalar. ScalarCompatibilityFixtures.invalidExplicitScalarTags
Merge keys Keeps << as an ordinary mapping entry; it does not flatten merged keys. UnsupportedYAMLGapsFixtures.fallbackValues, DownstreamDocumentTests
Unsupported built-in tags such as !!timestamp, !!binary, !!set, and !!omap Keeps parseable value trees without special tag semantics. UnsupportedYAMLGapsFixtures.fallbackValues
Sexagesimal-style scalars and date-looking plain scalars Keep string values for currently unsupported spellings such as 1:20, 2002-04-28, and 09. ScalarCompatibilityFixtures.unsupportedScalars
Custom constructors, custom resolvers, and environment expansion Not implemented. Build project-specific conversion on top of Model.Value or typed Codable. Planned future work
Foundation-specific scalar conversions such as Data, Date, or URL strategies Not special-cased in the library target. Encode explicit strings or typed models instead. Planned future work

Migration Checklist

  1. Audit the YAML corpus the caller actually reads and writes.
  2. Classify each document against the supported and unsupported tables above.
  3. Add representative fixtures for project-specific documents before switching call sites.
  4. Parse through PureYAML.parse(_:) and run PureYAML.validate(_:) before typed decoding when duplicate-key visibility matters.
  5. Prefer typed Codable for known schemas and PureYAML.Model.Value for inspection, migration tooling, or unsupported-shape triage.
  6. Run macOS, Linux, and WASM gates before publishing the migration.

When Not to Migrate Yet

Do not migrate a caller yet if it requires:

  • multi-document stream loading or dumping;
  • YAML merge-key flattening;
  • complex mapping keys as first-class keys;
  • binary or timestamp conversion into Foundation types;
  • arbitrary Any load and dump APIs;
  • custom scalar constructors or resolvers;
  • a full YAML 1.2 compliance claim.

In those cases, add a fixture and a child issue before changing production call sites.