docs(migration): document support boundaries
This commit is contained in:
parent
f3f6f15b32
commit
398df87f28
@ -76,6 +76,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
multiline content and exact quoted fallbacks.
|
||||
- Add downstream-shaped document fixtures for API-style documents, service
|
||||
configuration decoding, and unsupported merge-key fallback behavior.
|
||||
- Add usage and migration documentation that states tested APIs, support
|
||||
boundaries, unsupported YAML behavior, and cross-platform verification gates.
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@ -89,6 +89,13 @@ PureYAML is informed by Yams and its bundled `CYaml` / libyaml-derived parser,
|
||||
but it does not copy their implementation into `Sources/`. See
|
||||
[ATTRIBUTION.md](ATTRIBUTION.md).
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Usage](docs/USAGE.md): public APIs, validation, emitter options, and
|
||||
cross-platform gates.
|
||||
- [Migration and support boundaries](docs/MIGRATION.md): what PureYAML can
|
||||
replace today and which YAML features are deliberately unsupported.
|
||||
|
||||
## Usage
|
||||
|
||||
The examples in this section are covered by
|
||||
|
||||
96
docs/MIGRATION.md
Normal file
96
docs/MIGRATION.md
Normal file
@ -0,0 +1,96 @@
|
||||
# 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](../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.
|
||||
129
docs/USAGE.md
Normal file
129
docs/USAGE.md
Normal file
@ -0,0 +1,129 @@
|
||||
# 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
|
||||
|
||||
Until the first tagged release, use the `main` branch:
|
||||
|
||||
```swift
|
||||
.package(url: "https://github.com/mihaelamj/PureYAML.git", branch: "main")
|
||||
```
|
||||
|
||||
Add the product to the target that reads or writes YAML:
|
||||
|
||||
```swift
|
||||
.product(name: "PureYAML", package: "PureYAML")
|
||||
```
|
||||
|
||||
Then import the library:
|
||||
|
||||
```swift
|
||||
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` |
|
||||
| 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 |
|
||||
| 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` |
|
||||
|
||||
## 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.
|
||||
|
||||
## Typed Conversion
|
||||
|
||||
Use typed conversion when the YAML shape is already known. Current coverage
|
||||
includes:
|
||||
|
||||
- scalar `Decodable` and `Encodable` values;
|
||||
- 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 `super` coders.
|
||||
|
||||
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.
|
||||
|
||||
## Cross-Platform Verification
|
||||
|
||||
Before relying on a migration, run the same gates used by the repository:
|
||||
|
||||
```sh
|
||||
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](MIGRATION.md) and compare your input corpus with
|
||||
the supported and unsupported behavior listed there.
|
||||
Loading…
Reference in New Issue
Block a user