Slice 2 of #92. Add PureXML.read, a deterministic recovering reader: it never throws and never traps, returning the maximal best-effort tree plus one located Diagnostic per problem. - ReadResult { node, diagnostics } is the Equatable result type, so a deterministic read can be compared whole. - Diagnostic carries a message and a structured source Mark; a thrown ParseError maps to one directly (ParseError.mark exposes the position each case carries). - The reader resynchronizes after a failure (EventReader.recover(from:)): progress-aware, so a failure that already consumed the bad construct retries from there, while a stuck failure skips to the next markup start; it always advances when input remains, guaranteeing termination. - The tree builder assembles leniently: elements left open by truncation are closed, an end tag with no open element is dropped. Well-formed input yields exactly parse(_:)'s tree with no diagnostics. Tests pin exact trees and diagnostics for truncation, mismatched tags, and stray junk, prove determinism (same bytes give an identical ReadResult), and fuzz 400 seeded inputs (arbitrary plus truncated valid docs) asserting no crash. Recovery here is resync-based; finer in-reader recovery (keep the element on a duplicate attribute, pop to a matching open tag) is the next slice.
19 lines
741 B
Swift
19 lines
741 B
Swift
public extension PureXML.Parsing {
|
|
/// The outcome of a recovering read: the best-effort node tree and every
|
|
/// located ``Diagnostic`` found along the way. Equatable, so a deterministic
|
|
/// read can be compared whole.
|
|
struct ReadResult: Equatable, Sendable {
|
|
/// The best-effort tree. Always a document node; as complete as recovery
|
|
/// allowed.
|
|
public var node: PureXML.Model.Node
|
|
/// One diagnostic per problem, in source order. Empty when the input was
|
|
/// well-formed.
|
|
public var diagnostics: [Diagnostic]
|
|
|
|
public init(node: PureXML.Model.Node, diagnostics: [Diagnostic]) {
|
|
self.node = node
|
|
self.diagnostics = diagnostics
|
|
}
|
|
}
|
|
}
|