Files
2022-07-30 20:47:39 +02:00

94 lines
2.9 KiB
Swift

//
// SwiftGenKit
// Copyright © 2022 SwiftGen
// MIT Licence
//
import Foundation
import PathKit
import Yams
public enum YAML {
/// Read the contents of a YAML file located at the given path (only the first document).
///
/// - parameter path: The path to the YAML file
/// - returns: The decoded document
public static func read(path: Path, env: [String: String] = [:]) throws -> Any? {
let contents: String = try path.read()
return try decode(string: contents, env: env)
}
/// Decode the contents of YAML string (only the first document).
///
/// - parameter string: The YAML string
/// - returns: The decoded document
public static func decode(string: String, env: [String: String] = [:]) throws -> Any? {
try Yams.load(yaml: string, .default, Constructor.swiftgenContructor(env: env))
}
/// Encode the given object to YAML and write it to the given path
///
/// - parameter object: The object to encode
/// - parameter path: The path to the output file
public static func write(object: Any, to path: Path) throws {
let string = try encode(object: object)
try path.write(string)
}
/// Encode the given object to YAML and return it as a string
///
/// - parameter object: The object to encode
/// - returns: The encoded YAML string
public static func encode(object: Any) throws -> String {
let node = try represent(object: object)
return try Yams.serialize(node: node)
}
private static func represent(object: Any) throws -> Node {
switch object {
case let string as String:
return Node(string, .implicit, .doubleQuoted)
case let array as [Any]:
return Node(try array.map(represent), Tag(.seq))
case let dictionary as [String: Any]:
let pairs = try dictionary.map { (Node($0.key), try represent(object: $0.value)) }
return Node(pairs.sorted { $0.0 < $1.0 }, Tag(.map))
case let representable as NodeRepresentable:
return try representable.represented()
default:
throw YamlError.representer(problem: "Failed to represent \(object) as a Yams.Node")
}
}
}
// Copied from https://github.com/realm/SwiftLint/blob/0.29.2/Source/SwiftLintFramework/Models/YamlParser.swift
private extension Constructor {
static func swiftgenContructor(env: [String: String]) -> Constructor {
Constructor(customScalarMap(env: env))
}
static func customScalarMap(env: [String: String]) -> ScalarMap {
var map = defaultScalarMap
map[.str] = String.constructExpandingEnvVars(env: env)
return map
}
}
private extension String {
static func constructExpandingEnvVars(env: [String: String]) -> (_ scalar: Node.Scalar) -> String? {
{ (scalar: Node.Scalar) -> String? in
scalar.string.expandingEnvVars(env: env)
}
}
func expandingEnvVars(env: [String: String]) -> String {
var result = self
for (key, value) in env {
result = result.replacingOccurrences(of: "${\(key)}", with: value)
}
return result
}
}