import Foundation import Yams /// A `Sendable` snapshot of a parsed YAML value. Mappings keep document order; this is a /// read-only view — the engine never serializes through it (see `FrontmatterDocument`). public enum YAMLValue: Sendable, Equatable { case null case bool(Bool) case int(Int) case double(Double) case string(String) case date(Date) case sequence([YAMLValue]) case mapping([Pair]) public struct Pair: Sendable, Equatable { public let key: YAMLValue public let value: YAMLValue public init(key: YAMLValue, value: YAMLValue) { self.key = key self.value = value } } } extension YAMLValue { init(_ node: Node, resolver: Resolver = .default) { switch node { case let .scalar(scalar): self = YAMLValue(scalar: scalar, tag: resolver.resolveTag(of: node)) case let .sequence(sequence): self = .sequence(sequence.map { YAMLValue($0, resolver: resolver) }) case let .mapping(mapping): self = .mapping(mapping.map { Pair(key: YAMLValue($0.key, resolver: resolver), value: YAMLValue($0.value, resolver: resolver)) }) case .alias: self = .null } } private init(scalar: Node.Scalar, tag: Tag.Name) { switch tag { case .null: self = .null case .bool: self = Bool.construct(from: scalar).map(YAMLValue.bool) ?? .string(scalar.string) case .int: self = Int.construct(from: scalar).map(YAMLValue.int) ?? Double.construct(from: scalar).map(YAMLValue.double) ?? .string(scalar.string) case .float: self = Double.construct(from: scalar).map(YAMLValue.double) ?? .string(scalar.string) case .timestamp: self = Date.construct(from: scalar).map(YAMLValue.date) ?? .string(scalar.string) default: self = .string(scalar.string) } } } extension YAMLValue: CustomStringConvertible { /// Diagnostic rendering only — never used to write files. public var description: String { switch self { case .null: "null" case let .bool(value): value ? "true" : "false" case let .int(value): String(value) case let .double(value): String(value) case let .string(value): value case let .date(value): value.formatted(.iso8601) case let .sequence(values): "[" + values.map(\.description).joined(separator: ", ") + "]" case let .mapping(pairs): "{" + pairs.map { "\($0.key.description): \($0.value.description)" }.joined(separator: ", ") + "}" } } }