103 lines
2.8 KiB
Swift
103 lines
2.8 KiB
Swift
public extension PureYAML.Emitting {
|
|
/// Block-style YAML serializer for ``PureYAML/Model/Value``.
|
|
struct Dumper: Sendable {
|
|
public init() {}
|
|
|
|
public func dump(_ value: PureYAML.Model.Value) -> String {
|
|
render(value, indent: 0).joined(separator: "\n") + "\n"
|
|
}
|
|
}
|
|
}
|
|
|
|
extension PureYAML.Emitting.Dumper {
|
|
func render(
|
|
_ value: PureYAML.Model.Value,
|
|
indent: Int,
|
|
) -> [String] {
|
|
switch value {
|
|
case let .mapping(mapping):
|
|
renderMapping(mapping, indent: indent)
|
|
case let .sequence(values):
|
|
renderSequence(values, indent: indent)
|
|
default:
|
|
[String(repeating: " ", count: indent) + renderScalar(value)]
|
|
}
|
|
}
|
|
|
|
func renderMapping(
|
|
_ mapping: PureYAML.Model.Mapping,
|
|
indent: Int,
|
|
) -> [String] {
|
|
let prefix = String(repeating: " ", count: indent)
|
|
return mapping.pairs.flatMap { pair in
|
|
switch pair.value {
|
|
case .mapping, .sequence:
|
|
[prefix + escapeKey(pair.key) + ":"] + render(pair.value, indent: indent + 2)
|
|
default:
|
|
[prefix + escapeKey(pair.key) + ": " + renderScalar(pair.value)]
|
|
}
|
|
}
|
|
}
|
|
|
|
func renderSequence(
|
|
_ values: [PureYAML.Model.Value],
|
|
indent: Int,
|
|
) -> [String] {
|
|
let prefix = String(repeating: " ", count: indent)
|
|
return values.flatMap { value in
|
|
switch value {
|
|
case .mapping, .sequence:
|
|
[prefix + "-"] + render(value, indent: indent + 2)
|
|
default:
|
|
[prefix + "- " + renderScalar(value)]
|
|
}
|
|
}
|
|
}
|
|
|
|
func renderScalar(_ value: PureYAML.Model.Value) -> String {
|
|
switch value {
|
|
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):
|
|
quote(value)
|
|
case .sequence, .mapping:
|
|
""
|
|
}
|
|
}
|
|
|
|
func escapeKey(_ key: String) -> String {
|
|
if key.isEmpty || key.contains(":") || key.contains("#") || key.contains("\n") {
|
|
return quote(key)
|
|
}
|
|
return key
|
|
}
|
|
|
|
func quote(_ value: String) -> String {
|
|
var output = "\""
|
|
for character in value {
|
|
switch character {
|
|
case "\"":
|
|
output += "\\\""
|
|
case "\\":
|
|
output += "\\\\"
|
|
case "\n":
|
|
output += "\\n"
|
|
case "\r":
|
|
output += "\\r"
|
|
case "\t":
|
|
output += "\\t"
|
|
default:
|
|
output.append(character)
|
|
}
|
|
}
|
|
output += "\""
|
|
return output
|
|
}
|
|
}
|