PureYAML/Sources/PureYAMLJSON/JSON.Check.Builtins.swift
Mihaela Mihaljevic a8950e118c Merge conformance/yaml-test-suite-gaps: the libyaml port becomes the engine on main
The ported engine wins every conflict: main's post-fork patches to the
hand-rolled Scanner and TokenEventParser land on deleted files and are
dropped; their behaviors are carried by the port and guarded by the
whole-suite conformance gate (402/402 passing).

Merge adaptations, all gates green (style, namespacing, forbidden
patterns, changelog, roadmap, swiftformat, swiftlint strict, build,
full test suite, whole-suite conformance sweep):

- PureYAMLJSON representability rules move onto the Check algebra,
  replacing the retired legacy Rule type.
- The permissive tag-handle pre-pass is removed; the port rejects an
  undefined handle at parse time (suite case QLJ7) and the validation
  report carries it as a parse diagnostic.
- EventStreamComposer's nested types split one-per-file per the
  namespacing gate.
- Tests pinned to old-engine behavior were re-verified against the
  reference and updated: libyaml rejects an explicit-key continuation
  ending at a value colon, and suite case QB6E requires rejecting a
  quoted continuation at column 0.
- CHANGELOG unreleased entries from both lines are preserved in two
  groups with a provenance note.

Closes #1, closes #3
2026-07-05 00:23:48 +02:00

45 lines
1.9 KiB
Swift

import PureYAML
public extension PureYAML.Validation.BuiltinCheck {
/// Reports any mapping key that is not a string. JSON object names must be
/// strings, so a YAML complex key (a sequence or mapping used as a key) has no
/// JSON form. PureYAML core already ships ``mappingKeysAreUnique``; this check and
/// ``numbersAreFinite`` complete the JSON-representability set.
static var mappingKeysAreStrings: PureYAML.Validation.Check<PureYAML.Model.Mapping, PureYAML.Model.Value> {
PureYAML.Validation.Check(description: "Mapping keys are strings") { context in
context.subject.pairs.compactMap { pair in
guard pair.keyNode.stringValue == nil else {
return nil
}
return PureYAML.Validation.Issue(
severity: .error,
reason: "Mapping key '\(pair.keyNode.description)' is not a string",
path: context.path.appending(.complexKey(pair.keyNode)),
)
}
}
}
/// Reports any non-finite number (NaN or infinity). JSON has no literal for
/// these, so a value tree carrying one is not representable as JSON.
static var numbersAreFinite: PureYAML.Validation.Check<PureYAML.Model.Value, PureYAML.Model.Value> {
PureYAML.Validation.Check(description: "Numbers are finite") { context in
guard case let .double(number) = context.subject, !number.isFinite else {
return []
}
return [
PureYAML.Validation.Issue(
severity: .error,
reason: "Number '\(number)' is not finite",
path: context.path,
),
]
} when: { context in
if case .double = context.subject {
return true
}
return false
}
}
}