Add SE-0166 support
This commit is contained in:
parent
57ac824a76
commit
d06d6e03e6
|
@ -0,0 +1,454 @@
|
|||
//
|
||||
// Decoder.swift
|
||||
// Yams
|
||||
//
|
||||
// Created by Norio Nomura on 5/6/17.
|
||||
// Copyright (c) 2017 Yams. All rights reserved.
|
||||
//
|
||||
|
||||
#if swift(>=4.0)
|
||||
|
||||
import Foundation
|
||||
|
||||
public class YAMLDecoder {
|
||||
public init() {}
|
||||
public func decode<T: Swift.Decodable>(_ type: T.Type, from data: Data) throws -> T {
|
||||
// TODO: Detect string encoding
|
||||
let yaml = String(data: data, encoding: .utf8)! // swiftlint:disable:this force_unwrapping
|
||||
let node = try Yams.compose(yaml: yaml) ?? ""
|
||||
let decoder = _YAMLDecoder(referencing: node)
|
||||
return try T(from: decoder)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class _YAMLDecoder: Decoder {
|
||||
|
||||
let node: Node
|
||||
|
||||
init(referencing node: Node, codingPath: [CodingKey?] = []) {
|
||||
self.node = node
|
||||
self.codingPath = codingPath
|
||||
}
|
||||
|
||||
// MARK: - Swift.Decoder Methods
|
||||
|
||||
/// The path to the current point in encoding.
|
||||
var codingPath: [CodingKey?]
|
||||
|
||||
/// Contextual user-provided information for use during encoding.
|
||||
var userInfo: [CodingUserInfoKey : Any] = [:]
|
||||
|
||||
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
|
||||
guard let mapping = node.mapping else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.valueNotFound(
|
||||
KeyedDecodingContainer<Key>.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get keyed decoding container -- found null value instead."
|
||||
)
|
||||
)
|
||||
}
|
||||
let wrapper = _YAMLKeyedDecodingContainer<Key>(decoder: self, wrapping: mapping)
|
||||
return KeyedDecodingContainer(wrapper)
|
||||
}
|
||||
|
||||
func unkeyedContainer() throws -> UnkeyedDecodingContainer {
|
||||
guard let sequence = node.sequence else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.valueNotFound(
|
||||
UnkeyedDecodingContainer.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get unkeyed decoding container -- found null value instead."
|
||||
)
|
||||
)
|
||||
}
|
||||
return _YAMLUnkeyedDecodingContainer(decoder: self, wrapping: sequence)
|
||||
}
|
||||
|
||||
func singleValueContainer() throws -> SingleValueDecodingContainer {
|
||||
guard node.isScalar else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.valueNotFound(
|
||||
UnkeyedDecodingContainer.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get unkeyed decoding container -- found null value instead."
|
||||
)
|
||||
)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Performs the given closure with the given key pushed onto the end of the current coding path.
|
||||
///
|
||||
/// - parameter key: The key to push. May be nil for unkeyed containers.
|
||||
/// - parameter work: The work to perform with the key in the path.
|
||||
func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
|
||||
self.codingPath.append(key)
|
||||
let ret: T = try work()
|
||||
self.codingPath.removeLast()
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct _YAMLKeyedDecodingContainer<K: CodingKey> : KeyedDecodingContainerProtocol {
|
||||
|
||||
typealias Key = K
|
||||
|
||||
let decoder: _YAMLDecoder
|
||||
let mapping: Node.Mapping
|
||||
|
||||
init(decoder: _YAMLDecoder, wrapping mapping: Node.Mapping) {
|
||||
self.decoder = decoder
|
||||
self.mapping = mapping
|
||||
}
|
||||
|
||||
// MARK: - KeyedDecodingContainerProtocol
|
||||
|
||||
var codingPath: [CodingKey?] {
|
||||
return decoder.codingPath
|
||||
}
|
||||
|
||||
var allKeys: [Key] {
|
||||
return mapping.keys.flatMap { $0.string.flatMap(Key.init(stringValue:)) }
|
||||
}
|
||||
|
||||
func contains(_ key: K) -> Bool {
|
||||
if mapping[key.stringValue] != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? { return try construct(for: key) }
|
||||
func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? { return try construct(for: key) }
|
||||
|
||||
func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T : Decodable {
|
||||
return try decoder.with(pushedKey: key) {
|
||||
guard let node = mapping[key.stringValue] else { return nil }
|
||||
if T.self == Data.self {
|
||||
return Data.construct(from: node) as? T
|
||||
} else if T.self == Date.self {
|
||||
return Date.construct(from: node) as? T
|
||||
}
|
||||
|
||||
let decoder = _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
return try T(from: decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type,
|
||||
forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
|
||||
return try decoder.with(pushedKey: key) {
|
||||
guard let node = mapping[key.stringValue] else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.keyNotFound(
|
||||
key,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get \(KeyedDecodingContainer<NestedKey>.self) -- no value found for key \"\(key.stringValue)\""
|
||||
)
|
||||
)
|
||||
}
|
||||
guard let mapping = node.mapping else {
|
||||
fatalError("should throw type mismatch error")
|
||||
}
|
||||
let decoder = _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
let wrapping = _YAMLKeyedDecodingContainer<NestedKey>(decoder: decoder, wrapping: mapping)
|
||||
return KeyedDecodingContainer(wrapping)
|
||||
}
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
|
||||
return try decoder.with(pushedKey: key) {
|
||||
guard let node = mapping[key.stringValue], let sequence = node.sequence else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.keyNotFound(
|
||||
key,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get UnkeyedDecodingContainer -- no value found for key \"\(key.stringValue)\""
|
||||
)
|
||||
)
|
||||
}
|
||||
let decoder = _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
return _YAMLUnkeyedDecodingContainer(decoder: decoder, wrapping: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
|
||||
return try self.decoder.with(pushedKey: key) {
|
||||
guard let node = mapping[key.stringValue] else {
|
||||
throw DecodingError.keyNotFound(
|
||||
key,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get superDecoder() -- no value found for key \"\(key.stringValue)\""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
}
|
||||
}
|
||||
|
||||
func superDecoder() throws -> Decoder {
|
||||
return try _superDecoder(forKey: _YAMLDecodingSuperKey())
|
||||
}
|
||||
|
||||
func superDecoder(forKey key: Key) throws -> Decoder {
|
||||
return try _superDecoder(forKey: key)
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Encode ScalarConstructible
|
||||
func construct<T: ScalarConstructible>(for key: Key) throws -> T? {
|
||||
return decoder.with(pushedKey: key) {
|
||||
guard let node = mapping[key.stringValue] else { return nil }
|
||||
return T.construct(from: node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct _YAMLDecodingSuperKey: CodingKey {
|
||||
init() {}
|
||||
|
||||
var stringValue: String { return "super" }
|
||||
init?(stringValue: String) {
|
||||
guard stringValue == "super" else { return nil }
|
||||
}
|
||||
|
||||
var intValue: Int? { return nil }
|
||||
init?(intValue: Int) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct _YAMLUnkeyedDecodingContainer: UnkeyedDecodingContainer {
|
||||
|
||||
let decoder: _YAMLDecoder
|
||||
let sequence: Node.Sequence
|
||||
|
||||
/// The index of the element we're about to decode.
|
||||
var currentIndex: Int
|
||||
|
||||
init(decoder: _YAMLDecoder, wrapping sequence: Node.Sequence) {
|
||||
self.decoder = decoder
|
||||
self.sequence = sequence
|
||||
self.currentIndex = 0
|
||||
}
|
||||
|
||||
// MARK: - UnkeyedDecodingContainer
|
||||
var codingPath: [CodingKey?] {
|
||||
return decoder.codingPath
|
||||
}
|
||||
|
||||
var count: Int? {
|
||||
return sequence.count
|
||||
}
|
||||
|
||||
var isAtEnd: Bool {
|
||||
return self.currentIndex >= sequence.count
|
||||
}
|
||||
|
||||
mutating func decodeIfPresent(_ type: Bool.Type) throws -> Bool? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Int.Type) throws -> Int? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Int8.Type) throws -> Int8? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Int16.Type) throws -> Int16? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Int32.Type) throws -> Int32? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Int64.Type) throws -> Int64? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: UInt.Type) throws -> UInt? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: UInt8.Type) throws -> UInt8? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: UInt16.Type) throws -> UInt16? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: UInt32.Type) throws -> UInt32? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: UInt64.Type) throws -> UInt64? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Float.Type) throws -> Float? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: Double.Type) throws -> Double? { return try construct() }
|
||||
mutating func decodeIfPresent(_ type: String.Type) throws -> String? { return try construct() }
|
||||
|
||||
mutating func decodeIfPresent<T>(_ type: T.Type) throws -> T? where T : Decodable {
|
||||
guard !self.isAtEnd else { return nil }
|
||||
|
||||
let decoded: T? = try decoder.with(pushedKey: nil) {
|
||||
let node = sequence[currentIndex]
|
||||
if T.self == Data.self {
|
||||
return Data.construct(from: node) as? T
|
||||
} else if T.self == Date.self {
|
||||
return Date.construct(from: node) as? T
|
||||
}
|
||||
|
||||
let decoder = _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
return try T(from: decoder)
|
||||
}
|
||||
currentIndex += 1
|
||||
return decoded
|
||||
}
|
||||
|
||||
mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
|
||||
return try decoder.with(pushedKey: nil) {
|
||||
guard !self.isAtEnd else {
|
||||
throw DecodingError.valueNotFound(
|
||||
KeyedDecodingContainer<NestedKey>.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get nested keyed container -- unkeyed container is at end."
|
||||
)
|
||||
)
|
||||
}
|
||||
let node = sequence[currentIndex]
|
||||
guard let mapping = node.mapping else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.valueNotFound(
|
||||
KeyedDecodingContainer<NestedKey>.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get \(KeyedDecodingContainer<NestedKey>.self) -- no value found at index \"\(currentIndex)\""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
currentIndex += 1
|
||||
let decoder = _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
let wrapping = _YAMLKeyedDecodingContainer<NestedKey>(decoder: decoder, wrapping: mapping)
|
||||
return KeyedDecodingContainer(wrapping)
|
||||
}
|
||||
}
|
||||
|
||||
mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
|
||||
return try decoder.with(pushedKey: nil) {
|
||||
guard !self.isAtEnd else {
|
||||
throw DecodingError.valueNotFound(
|
||||
UnkeyedDecodingContainer.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get UnkeyedDecodingContainer -- unkeyed container is at end."
|
||||
)
|
||||
)
|
||||
}
|
||||
let node = sequence[currentIndex]
|
||||
guard let sequence = node.sequence else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.typeMismatch(
|
||||
type(of: node),
|
||||
DecodingError.Context(
|
||||
codingPath: codingPath,
|
||||
debugDescription: "Cannot get UnkeyedDecodingContainer -- no value found at index \"\(currentIndex)\""
|
||||
)
|
||||
)
|
||||
}
|
||||
let decoder = _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
return _YAMLUnkeyedDecodingContainer(decoder: decoder, wrapping: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
mutating func superDecoder() throws -> Decoder {
|
||||
return try decoder.with(pushedKey: nil) {
|
||||
guard !self.isAtEnd else {
|
||||
throw DecodingError.valueNotFound(
|
||||
Decoder.self,
|
||||
DecodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot get superDecoder() -- unkeyed container is at end."
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let node = sequence[currentIndex]
|
||||
self.currentIndex += 1
|
||||
return _YAMLDecoder(referencing: node, codingPath: self.decoder.codingPath)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Encode ScalarConstructible
|
||||
mutating func construct<T: ScalarConstructible>() throws -> T? {
|
||||
guard !self.isAtEnd else { return nil }
|
||||
|
||||
return decoder.with(pushedKey: nil) {
|
||||
let node = sequence[currentIndex]
|
||||
currentIndex += 1
|
||||
return T.construct(from: node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension _YAMLDecoder : SingleValueDecodingContainer {
|
||||
|
||||
// MARK: SingleValueDecodingContainer Methods
|
||||
|
||||
func decode(_ type: Bool.Type) throws -> Bool { return try construct() }
|
||||
func decode(_ type: Int.Type) throws -> Int { return try construct() }
|
||||
func decode(_ type: Int8.Type) throws -> Int8 { return try construct() }
|
||||
func decode(_ type: Int16.Type) throws -> Int16 { return try construct() }
|
||||
func decode(_ type: Int32.Type) throws -> Int32 { return try construct() }
|
||||
func decode(_ type: Int64.Type) throws -> Int64 { return try construct() }
|
||||
func decode(_ type: UInt.Type) throws -> UInt { return try construct() }
|
||||
func decode(_ type: UInt8.Type) throws -> UInt8 { return try construct() }
|
||||
func decode(_ type: UInt16.Type) throws -> UInt16 { return try construct() }
|
||||
func decode(_ type: UInt32.Type) throws -> UInt32 { return try construct() }
|
||||
func decode(_ type: UInt64.Type) throws -> UInt64 { return try construct() }
|
||||
func decode(_ type: Float.Type) throws -> Float { return try construct() }
|
||||
func decode(_ type: Double.Type) throws -> Double { return try construct() }
|
||||
func decode(_ type: String.Type) throws -> String { return try construct() }
|
||||
func decode(_ type: Data.Type) throws -> Data { return try construct() }
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Encode ScalarConstructible
|
||||
func construct<T: ScalarConstructible>() throws -> T {
|
||||
return try with(pushedKey: nil) {
|
||||
guard let decoded = T.construct(from: node) else {
|
||||
// FIXME: Should throw type mismatch error
|
||||
throw DecodingError.typeMismatch(
|
||||
T.self,
|
||||
DecodingError.Context(
|
||||
codingPath: codingPath, debugDescription: ""
|
||||
)
|
||||
)
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension BinaryInteger {
|
||||
public static func construct(from node: Node) -> Self? {
|
||||
return Int.construct(from: node) as? Self
|
||||
}
|
||||
}
|
||||
|
||||
extension Int16: ScalarConstructible {}
|
||||
extension Int32: ScalarConstructible {}
|
||||
extension Int64: ScalarConstructible {}
|
||||
extension Int8: ScalarConstructible {}
|
||||
extension UInt: ScalarConstructible {}
|
||||
extension UInt16: ScalarConstructible {}
|
||||
extension UInt32: ScalarConstructible {}
|
||||
extension UInt64: ScalarConstructible {}
|
||||
extension UInt8: ScalarConstructible {}
|
||||
|
||||
extension Float: ScalarConstructible {
|
||||
public static func construct(from node: Node) -> Float? {
|
||||
return Double.construct(from: node) as? Float
|
||||
}
|
||||
}
|
||||
|
||||
#endif // swiftlint:disable:this file_length
|
|
@ -0,0 +1,324 @@
|
|||
//
|
||||
// Encoder.swift
|
||||
// Yams
|
||||
//
|
||||
// Created by Norio Nomura on 5/2/17.
|
||||
// Copyright (c) 2017 Yams. All rights reserved.
|
||||
//
|
||||
|
||||
#if swift(>=4.0)
|
||||
|
||||
import Foundation
|
||||
|
||||
public class YAMLEncoder {
|
||||
public init() {}
|
||||
public func encode<T: Swift.Encodable>(_ value: T) throws -> Data {
|
||||
let encoder = _YAMLEncoder()
|
||||
try value.encode(to: encoder)
|
||||
return try serialize(node: encoder.node).data(using: .utf8, allowLossyConversion: false) ?? Data()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class _YAMLEncoder: Swift.Encoder {
|
||||
|
||||
var node: Node = ""
|
||||
|
||||
init(codingPath: [CodingKey?] = []) {
|
||||
self.codingPath = codingPath
|
||||
}
|
||||
|
||||
// MARK: - Swift.Encoder Methods
|
||||
|
||||
/// The path to the current point in encoding.
|
||||
var codingPath: [CodingKey?]
|
||||
|
||||
/// Contextual user-provided information for use during encoding.
|
||||
var userInfo: [CodingUserInfoKey : Any] = [:]
|
||||
|
||||
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> {
|
||||
assertCanRequestNewContainer()
|
||||
node = [:]
|
||||
let wrapper = _KeyedEncodingContainer<Key>(referencing: self)
|
||||
return KeyedEncodingContainer(wrapper)
|
||||
}
|
||||
|
||||
func unkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
assertCanRequestNewContainer()
|
||||
node = []
|
||||
return _UnkeyedEncodingContainer(referencing: self)
|
||||
}
|
||||
|
||||
func singleValueContainer() -> SingleValueEncodingContainer {
|
||||
assertCanRequestNewContainer()
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Performs the given closure with the given key pushed onto the end of the current coding path.
|
||||
///
|
||||
/// - parameter key: The key to push. May be nil for unkeyed containers.
|
||||
/// - parameter work: The work to perform with the key in the path.
|
||||
func with(pushedKey key: CodingKey?, _ work: () throws -> Void) rethrows {
|
||||
self.codingPath.append(key)
|
||||
try work()
|
||||
self.codingPath.removeLast()
|
||||
}
|
||||
|
||||
/// Asserts that a new container can be requested at this coding path.
|
||||
/// `preconditionFailure()`s if one cannot be requested.
|
||||
func assertCanRequestNewContainer() {
|
||||
guard node == "" else {
|
||||
let previousContainerType: String
|
||||
switch node {
|
||||
case .mapping:
|
||||
previousContainerType = "keyed"
|
||||
case .sequence:
|
||||
previousContainerType = "unkeyed"
|
||||
case .scalar:
|
||||
previousContainerType = "single value"
|
||||
}
|
||||
preconditionFailure(
|
||||
"Attempt to encode with new container when already encoded with \(previousContainerType) container."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class _YAMLReferencingEncoder: _YAMLEncoder {
|
||||
enum Reference {
|
||||
case sequence(Int)
|
||||
case mapping(String)
|
||||
}
|
||||
let encoder: _YAMLEncoder
|
||||
let reference: Reference
|
||||
|
||||
init(referencing encoder: _YAMLEncoder, at index: Int) {
|
||||
self.encoder = encoder
|
||||
reference = .sequence(index)
|
||||
super.init(codingPath: encoder.codingPath)
|
||||
}
|
||||
|
||||
init(referencing encoder: _YAMLEncoder, key: String) {
|
||||
self.encoder = encoder
|
||||
reference = .mapping(key)
|
||||
super.init(codingPath: encoder.codingPath)
|
||||
}
|
||||
|
||||
deinit {
|
||||
switch reference {
|
||||
case .sequence(let index):
|
||||
encoder.node[index] = node
|
||||
case .mapping(let key):
|
||||
encoder.node[key] = node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct _KeyedEncodingContainer<K: CodingKey> : KeyedEncodingContainerProtocol {
|
||||
typealias Key = K
|
||||
|
||||
let encoder: _YAMLEncoder
|
||||
|
||||
init(referencing encoder: _YAMLEncoder) {
|
||||
self.encoder = encoder
|
||||
}
|
||||
|
||||
// MARK: - KeyedEncodingContainerProtocol
|
||||
|
||||
var codingPath: [CodingKey?] {
|
||||
return encoder.codingPath
|
||||
}
|
||||
|
||||
// assumes following methods never throws
|
||||
func encode(_ value: Bool?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Int?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Int8?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Int16?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Int32?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Int64?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: UInt?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: UInt8?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: UInt16?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: UInt32?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: UInt64?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Float?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: Double?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
func encode(_ value: String?, forKey key: Key) throws { try represent(value, for: key) }
|
||||
|
||||
func encode<T>(_ value: T?, forKey key: Key) throws where T : Encodable {
|
||||
try encoder.with(pushedKey: key) {
|
||||
if let value = value {
|
||||
if let data = value as? Data {
|
||||
encoder.node.sequence?.append(try data.represented())
|
||||
} else if let date = value as? Date {
|
||||
encoder.node.sequence?.append(try date.represented())
|
||||
} else {
|
||||
try value.encode(to: referencingEncoder(for: key.stringValue))
|
||||
}
|
||||
} else {
|
||||
encoder.node.sequence?.append(Node("null", Tag(.null)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type,
|
||||
forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
|
||||
let wrapper = _KeyedEncodingContainer<NestedKey>(referencing: referencingEncoder(for: key.stringValue))
|
||||
return KeyedEncodingContainer(wrapper)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
|
||||
return _UnkeyedEncodingContainer(referencing: referencingEncoder(for: key.stringValue))
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return referencingEncoder(for: "super")
|
||||
}
|
||||
|
||||
func superEncoder(forKey key: Key) -> Encoder {
|
||||
return referencingEncoder(for: key.stringValue)
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Encode NodeRepresentable
|
||||
private func represent<T: NodeRepresentable>(_ value: T, for key: Key) throws {
|
||||
// assumes this function is used for types that never throws.
|
||||
encoder.node.mapping?[key.stringValue] = try Node(value)
|
||||
}
|
||||
|
||||
private func referencingEncoder(for key: String) -> _YAMLReferencingEncoder {
|
||||
return _YAMLReferencingEncoder(referencing: self.encoder, key: key)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct _UnkeyedEncodingContainer: UnkeyedEncodingContainer {
|
||||
|
||||
let encoder: _YAMLEncoder
|
||||
|
||||
init(referencing encoder: _YAMLEncoder) {
|
||||
self.encoder = encoder
|
||||
}
|
||||
|
||||
// MARK: - UnkeyedEncodingContainer
|
||||
|
||||
var codingPath: [CodingKey?] {
|
||||
return encoder.codingPath
|
||||
}
|
||||
|
||||
func encode(_ value: Bool?) throws { try represent(value) }
|
||||
func encode(_ value: Int?) throws { try represent(value) }
|
||||
func encode(_ value: Int8?) throws { try represent(value) }
|
||||
func encode(_ value: Int16?) throws { try represent(value) }
|
||||
func encode(_ value: Int32?) throws { try represent(value) }
|
||||
func encode(_ value: Int64?) throws { try represent(value) }
|
||||
func encode(_ value: UInt?) throws { try represent(value) }
|
||||
func encode(_ value: UInt8?) throws { try represent(value) }
|
||||
func encode(_ value: UInt16?) throws { try represent(value) }
|
||||
func encode(_ value: UInt32?) throws { try represent(value) }
|
||||
func encode(_ value: UInt64?) throws { try represent(value) }
|
||||
func encode(_ value: Float?) throws { try represent(value) }
|
||||
func encode(_ value: Double?) throws { try represent(value) }
|
||||
func encode(_ value: String?) throws { try represent(value) }
|
||||
|
||||
func encode<T>(_ value: T?) throws where T : Encodable {
|
||||
// Since generic types may throw, the coding path needs to contain this key.
|
||||
try encoder.with(pushedKey: nil) {
|
||||
if let value = value {
|
||||
if let data = value as? Data {
|
||||
encoder.node.sequence?.append(try data.represented())
|
||||
} else if let date = value as? Date {
|
||||
encoder.node.sequence?.append(try date.represented())
|
||||
} else {
|
||||
try value.encode(to: referencingEncoder())
|
||||
}
|
||||
} else {
|
||||
encoder.node.sequence?.append(Node("null", Tag(.null)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
|
||||
let wrapper = _KeyedEncodingContainer<NestedKey>(referencing: referencingEncoder())
|
||||
return KeyedEncodingContainer(wrapper)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
return _UnkeyedEncodingContainer(referencing: referencingEncoder())
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return referencingEncoder()
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Encode NodeRepresentable
|
||||
private func represent<T: NodeRepresentable>(_ value: T) throws {
|
||||
// assumes this function is used for types that never throws.
|
||||
encoder.node.sequence?.append(try Node(value))
|
||||
}
|
||||
|
||||
private func referencingEncoder() -> _YAMLReferencingEncoder {
|
||||
let index: Int = encoder.node.sequence?.count ?? 0
|
||||
encoder.node.sequence?.append("")
|
||||
return _YAMLReferencingEncoder(referencing: self.encoder, at: index)
|
||||
}
|
||||
}
|
||||
|
||||
extension _YAMLEncoder: SingleValueEncodingContainer {
|
||||
|
||||
// MARK: - SingleValueEncodingContainer Methods
|
||||
|
||||
func encode(_ value: Bool) throws { try represent(value) }
|
||||
func encode(_ value: Int) throws { try represent(value) }
|
||||
func encode(_ value: Int8) throws { try represent(value) }
|
||||
func encode(_ value: Int16) throws { try represent(value) }
|
||||
func encode(_ value: Int32) throws { try represent(value) }
|
||||
func encode(_ value: Int64) throws { try represent(value) }
|
||||
func encode(_ value: UInt) throws { try represent(value) }
|
||||
func encode(_ value: UInt8) throws { try represent(value) }
|
||||
func encode(_ value: UInt16) throws { try represent(value) }
|
||||
func encode(_ value: UInt32) throws { try represent(value) }
|
||||
func encode(_ value: UInt64) throws { try represent(value) }
|
||||
func encode(_ value: Float) throws { try represent(value) }
|
||||
func encode(_ value: Double) throws { try represent(value) }
|
||||
|
||||
func encode(_ value: String) throws {
|
||||
assertCanEncodeSingleValue()
|
||||
node = Node(value)
|
||||
}
|
||||
|
||||
// MARK: Utility
|
||||
|
||||
/// Asserts that a single value can be encoded at the current coding path
|
||||
/// (i.e. that one has not already been encoded through this container).
|
||||
/// `preconditionFailure()`s if one cannot be encoded.
|
||||
///
|
||||
/// This is similar to assertCanRequestNewContainer above.
|
||||
func assertCanEncodeSingleValue() {
|
||||
guard node == "" else {
|
||||
let previousContainerType: String
|
||||
switch node {
|
||||
case .mapping:
|
||||
previousContainerType = "keyed"
|
||||
case .sequence:
|
||||
previousContainerType = "unkeyed"
|
||||
case .scalar:
|
||||
preconditionFailure("Attempt to encode multiple values in a single value container.")
|
||||
}
|
||||
preconditionFailure(
|
||||
"Attempt to encode with new container when already encoded with \(previousContainerType) container."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode NodeRepresentable
|
||||
func represent<T: NodeRepresentable>(_ value: T) throws {
|
||||
assertCanEncodeSingleValue()
|
||||
node = try Node(value)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,289 @@
|
|||
//
|
||||
// EncoderTests.swift
|
||||
// Yams
|
||||
//
|
||||
// Created by Norio Nomura on 5/2/17.
|
||||
// Copyright (c) 2017 Yams. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import Yams
|
||||
|
||||
#if swift(>=4.0)
|
||||
|
||||
/// Tests are copied from https://github.com/apple/swift/blob/master/test/stdlib/TestJSONEncoder.swift
|
||||
class EncoderTests: XCTestCase {
|
||||
// MARK: - Encoding Top-Level Empty Types
|
||||
func testEncodingTopLevelEmptyStruct() {
|
||||
let empty = EmptyStruct()
|
||||
_testRoundTrip(of: empty, expectedYAML: "{}\n")
|
||||
}
|
||||
|
||||
func testEncodingTopLevelEmptyClass() {
|
||||
let empty = EmptyClass()
|
||||
_testRoundTrip(of: empty, expectedYAML: "{}\n")
|
||||
}
|
||||
|
||||
// MARK: - Encoding Top-Level Single-Value Types
|
||||
func testEncodingTopLevelSingleValueEnum() {
|
||||
_testRoundTrip(of: Switch.off, expectedYAML: "false\n...\n")
|
||||
_testRoundTrip(of: Switch.on, expectedYAML: "true\n...\n")
|
||||
}
|
||||
|
||||
func testEncodingTopLevelSingleValueStruct() {
|
||||
_testRoundTrip(of: Timestamp(3141592653), expectedYAML: "3.141592653e+9\n...\n")
|
||||
}
|
||||
|
||||
func testEncodingTopLevelSingleValueClass() {
|
||||
_testRoundTrip(of: Counter())
|
||||
}
|
||||
|
||||
// MARK: - Encoding Top-Level Structured Types
|
||||
func testEncodingTopLevelStructuredStruct() {
|
||||
// Address is a struct type with multiple fields.
|
||||
let address = Address.testValue
|
||||
_testRoundTrip(of: address)
|
||||
}
|
||||
|
||||
func testEncodingTopLevelStructuredClass() {
|
||||
// Person is a class with multiple fields.
|
||||
let person = Person.testValue
|
||||
_testRoundTrip(of: person)
|
||||
}
|
||||
|
||||
func testEncodingTopLevelDeepStructuredType() {
|
||||
// Company is a type with fields which are Codable themselves.
|
||||
let company = Company.testValue
|
||||
_testRoundTrip(of: company)
|
||||
}
|
||||
|
||||
// MARK: - Date Strategy Tests
|
||||
func testEncodingDate() {
|
||||
// We can't encode a top-level Date, so it'll be wrapped in an array.
|
||||
_testRoundTrip(of: TopLevelWrapper(Date()))
|
||||
}
|
||||
|
||||
func testEncodingDateMillisecondsSince1970() {
|
||||
// Cannot encode an arbitrary number of seconds since we've lost precision since 1970.
|
||||
let seconds = 1000.0
|
||||
let expectedYAML = "- 1970-01-01T00:16:40Z\n"
|
||||
|
||||
// We can't encode a top-level Date, so it'll be wrapped in an array.
|
||||
_testRoundTrip(of: TopLevelWrapper(Date(timeIntervalSince1970: seconds)),
|
||||
expectedYAML: expectedYAML)
|
||||
}
|
||||
|
||||
// MARK: - Data Tests
|
||||
func testEncodingBase64Data() {
|
||||
let data = Data(bytes: [0xDE, 0xAD, 0xBE, 0xEF])
|
||||
|
||||
// We can't encode a top-level Data, so it'll be wrapped in an array.
|
||||
let expectedYAML = "- 3q2+7w==\n"
|
||||
_testRoundTrip(of: TopLevelWrapper(data), expectedYAML: expectedYAML)
|
||||
}
|
||||
|
||||
// MARK: - Helper Functions
|
||||
private func _testRoundTrip<T>(of value: T,
|
||||
expectedYAML yamlString: String? = nil) where T : Codable, T : Equatable {
|
||||
let yaml = yamlString?.data(using: .utf8)! // swiftlint:disable:this force_unwrapping
|
||||
var payload: Data! = nil
|
||||
do {
|
||||
let encoder = YAMLEncoder()
|
||||
payload = try encoder.encode(value)
|
||||
} catch {
|
||||
XCTFail("Failed to encode \(T.self) to YAML.")
|
||||
}
|
||||
|
||||
if let expectedYAML = yaml {
|
||||
XCTAssertEqual(expectedYAML, payload, "Produced YAML not identical to expected YAML.")
|
||||
}
|
||||
|
||||
do {
|
||||
let decoder = YAMLDecoder()
|
||||
let decoded = try decoder.decode(T.self, from: payload)
|
||||
XCTAssertEqual(decoded, value, "\(T.self) did not round-trip to an equal value.")
|
||||
} catch {
|
||||
XCTFail("Failed to decode \(T.self) from YAML by error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Empty Types
|
||||
fileprivate struct EmptyStruct: Codable, Equatable {
|
||||
static func == (_ lhs: EmptyStruct, _ rhs: EmptyStruct) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class EmptyClass: Codable, Equatable {
|
||||
static func == (_ lhs: EmptyClass, _ rhs: EmptyClass) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Single-Value Types
|
||||
/// A simple on-off switch type that encodes as a single Bool value.
|
||||
fileprivate enum Switch: Codable {
|
||||
case off
|
||||
case on // swiftlint:disable:this identifier_name
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
switch try container.decode(Bool.self) {
|
||||
case false: self = .off
|
||||
case true: self = .on
|
||||
}
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
switch self {
|
||||
case .off: try container.encode(false)
|
||||
case .on: try container.encode(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple timestamp type that encodes as a single Double value.
|
||||
fileprivate struct Timestamp: Codable, Equatable {
|
||||
let value: Double
|
||||
|
||||
init(_ value: Double) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
value = try container.decode(Double.self)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(self.value)
|
||||
}
|
||||
|
||||
static func == (lhs: Timestamp, rhs: Timestamp) -> Bool {
|
||||
return lhs.value == rhs.value
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple referential counter type that encodes as a single Int value.
|
||||
fileprivate final class Counter: Codable, Equatable {
|
||||
var count: Int = 0
|
||||
|
||||
init() {}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
count = try container.decode(Int.self)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(self.count)
|
||||
}
|
||||
|
||||
static func == (lhs: Counter, rhs: Counter) -> Bool {
|
||||
return lhs.count == rhs.count
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Structured Types
|
||||
/// A simple address type that encodes as a dictionary of values.
|
||||
fileprivate struct Address: Codable, Equatable {
|
||||
let street: String
|
||||
let city: String
|
||||
let state: String
|
||||
let zipCode: Int
|
||||
let country: String
|
||||
|
||||
init(street: String, city: String, state: String, zipCode: Int, country: String) {
|
||||
self.street = street
|
||||
self.city = city
|
||||
self.state = state
|
||||
self.zipCode = zipCode
|
||||
self.country = country
|
||||
}
|
||||
|
||||
static func == (_ lhs: Address, _ rhs: Address) -> Bool {
|
||||
return lhs.street == rhs.street &&
|
||||
lhs.city == rhs.city &&
|
||||
lhs.state == rhs.state &&
|
||||
lhs.zipCode == rhs.zipCode &&
|
||||
lhs.country == rhs.country
|
||||
}
|
||||
|
||||
static var testValue: Address {
|
||||
return Address(street: "1 Infinite Loop",
|
||||
city: "Cupertino",
|
||||
state: "CA",
|
||||
zipCode: 95014,
|
||||
country: "United States")
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple person class that encodes as a dictionary of values.
|
||||
fileprivate class Person: Codable, Equatable {
|
||||
let name: String
|
||||
let email: String
|
||||
|
||||
init(name: String, email: String) {
|
||||
self.name = name
|
||||
self.email = email
|
||||
}
|
||||
|
||||
static func == (_ lhs: Person, _ rhs: Person) -> Bool {
|
||||
return lhs.name == rhs.name && lhs.email == rhs.email
|
||||
}
|
||||
|
||||
static var testValue: Person {
|
||||
return Person(name: "Johnny Appleseed", email: "appleseed@apple.com")
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple company struct which encodes as a dictionary of nested values.
|
||||
fileprivate struct Company: Codable, Equatable {
|
||||
let address: Address
|
||||
var employees: [Person]
|
||||
|
||||
init(address: Address, employees: [Person]) {
|
||||
self.address = address
|
||||
self.employees = employees
|
||||
}
|
||||
|
||||
static func == (_ lhs: Company, _ rhs: Company) -> Bool {
|
||||
return lhs.address == rhs.address && lhs.employees == rhs.employees
|
||||
}
|
||||
|
||||
static var testValue: Company {
|
||||
return Company(address: Address.testValue, employees: [Person.testValue])
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper Types
|
||||
|
||||
/// Wraps a type T so that it can be encoded at the top level of a payload.
|
||||
fileprivate struct TopLevelWrapper<T> : Codable, Equatable where T : Codable, T : Equatable {
|
||||
let value: T
|
||||
|
||||
init(_ value: T) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.unkeyedContainer()
|
||||
try container.encode(value)
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
var container = try decoder.unkeyedContainer()
|
||||
value = try container.decode(T.self)
|
||||
assert(container.isAtEnd)
|
||||
}
|
||||
|
||||
static func == (_ lhs: TopLevelWrapper<T>, _ rhs: TopLevelWrapper<T>) -> Bool {
|
||||
return lhs.value == rhs.value
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -17,12 +17,15 @@
|
|||
6C3C90B91E0FFB6B009DEFE8 /* NodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3C90B81E0FFB6B009DEFE8 /* NodeTests.swift */; };
|
||||
6C4A22071DF8553C002A0206 /* String+Yams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4A22061DF8553C002A0206 /* String+Yams.swift */; };
|
||||
6C4A22091DF855BB002A0206 /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4A22081DF855BB002A0206 /* StringTests.swift */; };
|
||||
6C4AF3201EBE1705008775BC /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AF31E1EBE14A1008775BC /* Decoder.swift */; };
|
||||
6C6834C81E0281880047B4D1 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6834C71E0281880047B4D1 /* Node.swift */; };
|
||||
6C6834CC1E0283980047B4D1 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6834CB1E0283980047B4D1 /* Parser.swift */; };
|
||||
6C6834CD1E02847D0047B4D1 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6834C91E0281D90047B4D1 /* Tag.swift */; };
|
||||
6C6834D11E0297390047B4D1 /* SpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6834D01E0297390047B4D1 /* SpecTests.swift */; };
|
||||
6C6834D31E02B9760047B4D1 /* Resolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6834D21E02B9760047B4D1 /* Resolver.swift */; };
|
||||
6C6834D51E02BC1F0047B4D1 /* ResolverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6834D41E02BC1F0047B4D1 /* ResolverTests.swift */; };
|
||||
6C788A011EB87232005386F0 /* EncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C788A001EB87232005386F0 /* EncoderTests.swift */; };
|
||||
6C788A041EB89162005386F0 /* Encoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C788A021EB876C4005386F0 /* Encoder.swift */; };
|
||||
6C78C5651E29B27D0096215F /* RepresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C78C5631E29B1CE0096215F /* RepresenterTests.swift */; };
|
||||
6CBAEE1A1E3839500021BF87 /* Yams.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CBAEE191E3839500021BF87 /* Yams.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6CC2E33F1E22347B00F62269 /* Representer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC2E33E1E22347B00F62269 /* Representer.swift */; };
|
||||
|
@ -66,12 +69,15 @@
|
|||
6C4A22061DF8553C002A0206 /* String+Yams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Yams.swift"; sourceTree = "<group>"; };
|
||||
6C4A22081DF855BB002A0206 /* StringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; };
|
||||
6C4A220A1DF85793002A0206 /* LinuxMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxMain.swift; sourceTree = "<group>"; };
|
||||
6C4AF31E1EBE14A1008775BC /* Decoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decoder.swift; sourceTree = "<group>"; };
|
||||
6C6834C71E0281880047B4D1 /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = "<group>"; };
|
||||
6C6834C91E0281D90047B4D1 /* Tag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = "<group>"; };
|
||||
6C6834CB1E0283980047B4D1 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
|
||||
6C6834D01E0297390047B4D1 /* SpecTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpecTests.swift; sourceTree = "<group>"; };
|
||||
6C6834D21E02B9760047B4D1 /* Resolver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Resolver.swift; sourceTree = "<group>"; };
|
||||
6C6834D41E02BC1F0047B4D1 /* ResolverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResolverTests.swift; sourceTree = "<group>"; };
|
||||
6C788A001EB87232005386F0 /* EncoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncoderTests.swift; sourceTree = "<group>"; };
|
||||
6C788A021EB876C4005386F0 /* Encoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encoder.swift; sourceTree = "<group>"; };
|
||||
6C78C5631E29B1CE0096215F /* RepresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepresenterTests.swift; sourceTree = "<group>"; };
|
||||
6CBAEE191E3839500021BF87 /* Yams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Yams.h; sourceTree = "<group>"; };
|
||||
6CC2E33E1E22347B00F62269 /* Representer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Representer.swift; sourceTree = "<group>"; };
|
||||
|
@ -127,7 +133,9 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
6C0D2A351E0A934B00C45545 /* Constructor.swift */,
|
||||
6C4AF31E1EBE14A1008775BC /* Decoder.swift */,
|
||||
6CE603971E13502E00A13D8D /* Emitter.swift */,
|
||||
6C788A021EB876C4005386F0 /* Encoder.swift */,
|
||||
6CF025371E9CF4380061FB47 /* Mark.swift */,
|
||||
6C6834C71E0281880047B4D1 /* Node.swift */,
|
||||
6C0409AB1E607E9900C95D83 /* Node.Scalar.swift */,
|
||||
|
@ -160,6 +168,7 @@
|
|||
6CF6CE071E0E3A5900CB87D4 /* Fixtures */,
|
||||
6C0488ED1E0CBD56006F9F80 /* ConstructorTests.swift */,
|
||||
6C0A00D41E152D6200222704 /* EmitterTests.swift */,
|
||||
6C788A001EB87232005386F0 /* EncoderTests.swift */,
|
||||
6CF025391E9D12680061FB47 /* MarkTests.swift */,
|
||||
6C3C90B81E0FFB6B009DEFE8 /* NodeTests.swift */,
|
||||
6CF6CE081E0E3B1000CB87D4 /* PerformanceTests.swift */,
|
||||
|
@ -347,12 +356,14 @@
|
|||
E8EDB8881DE2181B0062268D /* loader.c in Sources */,
|
||||
E8EDB88C1DE2181B0062268D /* writer.c in Sources */,
|
||||
E8EDB88B1DE2181B0062268D /* scanner.c in Sources */,
|
||||
6C4AF3201EBE1705008775BC /* Decoder.swift in Sources */,
|
||||
6C0409AC1E607E9900C95D83 /* Node.Scalar.swift in Sources */,
|
||||
6C4A22071DF8553C002A0206 /* String+Yams.swift in Sources */,
|
||||
E8EDB8891DE2181B0062268D /* parser.c in Sources */,
|
||||
6CF025381E9CF4380061FB47 /* Mark.swift in Sources */,
|
||||
OBJ_50 /* YamlError.swift in Sources */,
|
||||
E8EDB88A1DE2181B0062268D /* reader.c in Sources */,
|
||||
6C788A041EB89162005386F0 /* Encoder.swift in Sources */,
|
||||
6C6834CD1E02847D0047B4D1 /* Tag.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -361,6 +372,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 0;
|
||||
files = (
|
||||
6C788A011EB87232005386F0 /* EncoderTests.swift in Sources */,
|
||||
6CF6CE091E0E3B1000CB87D4 /* PerformanceTests.swift in Sources */,
|
||||
6C4A22091DF855BB002A0206 /* StringTests.swift in Sources */,
|
||||
6C0488EC1E0BE113006F9F80 /* TestHelper.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue