forked from CoreOffice/XMLCoder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AttributedEnumIntrinsicTest.swift
121 lines (103 loc) · 3.75 KB
/
AttributedEnumIntrinsicTest.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// AttributedEnumIntrinsicTest.swift
// XMLCoder
//
// Created by Max Desiatov on 29/03/2019.
//
import Foundation
import XCTest
@testable import XMLCoder
let attributedEnumXML = """
<?xml version="1.0" encoding="UTF-8"?>
<foo><number type="string">ABC</number><number type="int">123</number></foo>
""".data(using: .utf8)!
private struct Foo2: Codable {
let number: [FooNumber]
}
private struct FooNumber: Codable, DynamicNodeEncoding {
public let type: FooEnum
public init(type: FooEnum) {
self.type = type
}
enum CodingKeys: String, CodingKey {
case type
case typeValue = ""
}
public static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
switch key {
case FooNumber.CodingKeys.type: return .attribute
default: return .element
}
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
type = try container.decode(FooEnum.self, forKey: .type)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch type {
case let .string(value):
try container.encode("string", forKey: .type)
try container.encode(value, forKey: .typeValue)
case let .int(value):
try container.encode("int", forKey: .type)
try container.encode(value, forKey: .typeValue)
}
}
}
private enum FooEnum: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case string
case int
}
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
if let value = try values.decodeIfPresent(String.self, forKey: .string) {
self = .string(value)
return
} else if let value = try values.decodeIfPresent(Int.self, forKey: .int) {
self = .int(value)
return
} else {
throw DecodingError.dataCorrupted(DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "No coded value for string or int"
))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case let .string(value):
try container.encode(value, forKey: .string)
case let .int(value):
try container.encode(value, forKey: .int)
}
}
case string(String)
case int(Int)
}
final class AttributedEnumIntrinsicTest: XCTestCase {
func testEncode() throws {
let encoder = XMLEncoder()
encoder.outputFormatting = []
let foo1 = Foo2(number: [FooNumber(type: FooEnum.string("ABC")), FooNumber(type: FooEnum.int(123))])
let header = XMLHeader(version: 1.0, encoding: "UTF-8")
let encoded = try encoder.encode(foo1, withRootKey: "foo", header: header)
let xmlString = String(data: encoded, encoding: .utf8)
XCTAssertNotNil(xmlString)
// Test string equivalency
let encodedXML = xmlString!.trimmingCharacters(in: .whitespacesAndNewlines)
let originalXML = String(data: attributedEnumXML, encoding: .utf8)!.trimmingCharacters(in: .whitespacesAndNewlines)
XCTAssertEqual(encodedXML, originalXML)
}
// TODO: Fix decoding
// func testDecode() throws {
// let decoder = XMLDecoder()
// decoder.errorContextLength = 10
//
// let foo = try decoder.decode(Foo2.self, from: attributedEnumXML)
// XCTAssertEqual(foo.number[0].type, FooEnum.string("ABC"))
// XCTAssertEqual(foo.number[1].type, FooEnum.int(123))
// }
}