Simplify `YAMLEncoder`

- Rename `ScalarRepresentableCustomizedForCodable` to `YAMLEncodable`
- Replace methods required by protocol with generic methods
This commit is contained in:
Norio Nomura 2018-03-22 23:27:14 +09:00
parent 3041d16db2
commit 18e173301d
No known key found for this signature in database
GPG Key ID: D4A7318EB7F7138D
2 changed files with 55 additions and 86 deletions

View File

@ -81,17 +81,6 @@ private class _Encoder: Swift.Encoder {
set { node.sequence = newValue }
}
/// Encode `ScalarRepresentable` to `node`
func represent<T: ScalarRepresentable>(_ value: T) throws {
assertCanEncodeNewValue()
node = try box(value)
}
func represent<T: ScalarRepresentableCustomizedForCodable>(_ value: T) throws {
assertCanEncodeNewValue()
node = value.representedForCodable()
}
/// create a new `_ReferencingEncoder` instance as `key` inheriting `userInfo`
func encoder(for key: CodingKey) -> _ReferencingEncoder {
return .init(referencing: self, key: key)
@ -102,19 +91,6 @@ private class _Encoder: Swift.Encoder {
return .init(referencing: self, at: index)
}
/// Create `Node` from `ScalarRepresentable`.
/// Errors throwed by `ScalarRepresentable` will be boxed into `EncodingError`
private func box(_ representable: ScalarRepresentable) throws -> Node {
do {
return try representable.represented()
} catch {
let context = EncodingError.Context(codingPath: codingPath,
debugDescription: "Unable to encode the given value to YAML.",
underlyingError: error)
throw EncodingError.invalidValue(representable, context)
}
}
private var canEncodeNewValue: Bool { return node == .unused }
}
@ -157,22 +133,9 @@ private struct _KeyedEncodingContainer<Key: CodingKey> : KeyedEncodingContainerP
// MARK: - Swift.KeyedEncodingContainerProtocol Methods
var codingPath: [CodingKey] { return encoder.codingPath }
func encodeNil(forKey key: Key) throws { encoder.mapping[key.stringValue] = .null }
func encode(_ value: Bool, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Int, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Int8, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Int16, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Int32, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Int64, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: UInt, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: UInt8, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: UInt16, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: UInt32, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: UInt64, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Float, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: Double, forKey key: Key) throws { try encoder(for: key).represent(value) }
func encode(_ value: String, forKey key: Key) throws { encoder.mapping[key.stringValue] = Node(value) }
func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable { try encoder(for: key).encode(value) }
func encodeNil(forKey key: Key) throws { encoder.mapping[key.stringValue] = .null }
func encode<T>(_ value: T, forKey key: Key) throws where T: YAMLEncodable { try encoder(for: key).encode(value) }
func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable { try encoder(for: key).encode(value) }
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type,
forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
@ -202,22 +165,9 @@ private struct _UnkeyedEncodingContainer: UnkeyedEncodingContainer {
var codingPath: [CodingKey] { return encoder.codingPath }
var count: Int { return encoder.sequence.count }
func encodeNil() throws { encoder.sequence.append(.null) }
func encode(_ value: Bool) throws { try currentEncoder.represent(value) }
func encode(_ value: Int) throws { try currentEncoder.represent(value) }
func encode(_ value: Int8) throws { try currentEncoder.represent(value) }
func encode(_ value: Int16) throws { try currentEncoder.represent(value) }
func encode(_ value: Int32) throws { try currentEncoder.represent(value) }
func encode(_ value: Int64) throws { try currentEncoder.represent(value) }
func encode(_ value: UInt) throws { try currentEncoder.represent(value) }
func encode(_ value: UInt8) throws { try currentEncoder.represent(value) }
func encode(_ value: UInt16) throws { try currentEncoder.represent(value) }
func encode(_ value: UInt32) throws { try currentEncoder.represent(value) }
func encode(_ value: UInt64) throws { try currentEncoder.represent(value) }
func encode(_ value: Float) throws { try currentEncoder.represent(value) }
func encode(_ value: Double) throws { try currentEncoder.represent(value) }
func encode(_ value: String) throws { encoder.sequence.append(Node(value)) }
func encode<T>(_ value: T) throws where T: Encodable { try currentEncoder.encode(value) }
func encodeNil() throws { encoder.sequence.append(.null) }
func encode<T>(_ value: T) throws where T: YAMLEncodable { try currentEncoder.encode(value) }
func encode<T>(_ value: T) throws where T: Encodable { try currentEncoder.encode(value) }
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
return currentEncoder.container(keyedBy: type)
@ -243,31 +193,15 @@ extension _Encoder: SingleValueEncodingContainer {
node = .null
}
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 {
func encode<T>(_ value: T) throws where T: YAMLEncodable {
assertCanEncodeNewValue()
node = Node(value)
node = value.box()
}
func encode<T>(_ value: T) throws where T: Encodable {
assertCanEncodeNewValue()
if let customized = value as? ScalarRepresentableCustomizedForCodable {
node = customized.representedForCodable()
} else if let representable = value as? ScalarRepresentable {
node = try box(representable)
if let encodable = value as? YAMLEncodable {
node = encodable.box()
} else {
try value.encode(to: self)
}

View File

@ -219,25 +219,52 @@ extension String: ScalarRepresentable {
/// MARK: - ScalarRepresentableCustomizedForCodable
public protocol ScalarRepresentableCustomizedForCodable: ScalarRepresentable {
func representedForCodable() -> Node
public protocol YAMLEncodable: Encodable {
func box() -> Node
}
extension Date: ScalarRepresentableCustomizedForCodable {
public func representedForCodable() -> Node {
extension YAMLEncodable where Self: ScalarRepresentable {
public func box() -> Node {
return .scalar(represented())
}
}
extension Bool: YAMLEncodable {}
extension Data: YAMLEncodable {}
extension Decimal: YAMLEncodable {}
extension Int: YAMLEncodable {}
extension Int8: YAMLEncodable {}
extension Int16: YAMLEncodable {}
extension Int32: YAMLEncodable {}
extension Int64: YAMLEncodable {}
extension UInt: YAMLEncodable {}
extension UInt8: YAMLEncodable {}
extension UInt16: YAMLEncodable {}
extension UInt32: YAMLEncodable {}
extension UInt64: YAMLEncodable {}
extension URL: YAMLEncodable {}
extension String: YAMLEncodable {}
extension Date: YAMLEncodable {
public func box() -> Node {
return Node(iso8601StringWithFullNanosecond, Tag(.timestamp))
}
}
extension Double: ScalarRepresentableCustomizedForCodable {}
extension Float: ScalarRepresentableCustomizedForCodable {}
extension FloatingPoint where Self: CVarArg {
public func representedForCodable() -> Node {
extension Double: YAMLEncodable {
public func box() -> Node {
return Node(formattedStringForCodable, Tag(.float))
}
}
private var formattedStringForCodable: String {
extension Float: YAMLEncodable {
public func box() -> Node {
return Node(formattedStringForCodable, Tag(.float))
}
}
private extension FloatingPoint where Self: CVarArg {
var formattedStringForCodable: String {
// Since `NumberFormatter` creates a string with insufficient precision for Decode,
// it uses with `String(format:...)`
#if os(Linux)
@ -252,3 +279,11 @@ extension FloatingPoint where Self: CVarArg {
return string
}
}
@available(*, unavailable, renamed: "YAMLEncodable")
typealias ScalarRepresentableCustomizedForCodable = YAMLEncodable
extension YAMLEncodable {
@available(*, unavailable, renamed: "box()")
func representedForCodable() -> Node { fatalError("unreachable") }
}