-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathKeyedEncodingContainer.swift
More file actions
103 lines (88 loc) · 3.67 KB
/
Copy pathKeyedEncodingContainer.swift
File metadata and controls
103 lines (88 loc) · 3.67 KB
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
import Foundation
extension _CBOREncoder {
final class KeyedContainer<Key: CodingKey> {
var storage: [AnyCodingKey: CBOREncodingContainer] = [:]
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
let options: CodableCBOREncoder._Options
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBOREncoder._Options) {
self.codingPath = codingPath
self.userInfo = userInfo
self.options = options
}
}
}
extension _CBOREncoder.KeyedContainer: KeyedEncodingContainerProtocol {
func encodeNil(forKey key: Key) throws {
var container = self.nestedSingleValueContainer(forKey: key)
try container.encodeNil()
}
func encode<T: Encodable>(_ value: T, forKey key: Key) throws {
var container = self.nestedSingleValueContainer(forKey: key)
try container.encode(value)
}
private func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] {
return self.codingPath + [key]
}
private func nestedSingleValueContainer(forKey key: Key) -> SingleValueEncodingContainer {
let container = _CBOREncoder.SingleValueContainer(
codingPath: self.nestedCodingPath(forKey: key),
userInfo: self.userInfo,
options: self.options
)
self.storage[anyCodingKeyForKey(key)] = container
return container
}
func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
let container = _CBOREncoder.UnkeyedContainer(
codingPath: self.nestedCodingPath(forKey: key),
userInfo: self.userInfo,
options: self.options
)
self.storage[anyCodingKeyForKey(key)] = container
return container
}
func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
let container = _CBOREncoder.KeyedContainer<NestedKey>(
codingPath: self.nestedCodingPath(forKey: key),
userInfo: self.userInfo,
options: self.options
)
self.storage[anyCodingKeyForKey(key)] = container
return KeyedEncodingContainer(container)
}
fileprivate func anyCodingKeyForKey(_ key: Key) -> AnyCodingKey {
return AnyCodingKey(key, useStringKey: self.options.useStringKeys)
}
func superEncoder() -> Encoder {
// Use a special "super" key for encoding class hierarchies
let superKey = AnyCodingKey(stringValue: "super")
let encoder = _CBOREncoder(options: self.options)
encoder.codingPath = self.codingPath + [superKey]
encoder.userInfo = self.userInfo
self.storage[superKey] = encoder
return encoder
}
func superEncoder(forKey key: Key) -> Encoder {
let encoder = _CBOREncoder(options: self.options)
encoder.codingPath = self.nestedCodingPath(forKey: key)
encoder.userInfo = self.userInfo
self.storage[anyCodingKeyForKey(key)] = encoder
return encoder
}
}
extension _CBOREncoder.KeyedContainer: CBOREncodingContainer {
var data: Data {
// TODO: Check that this works for all sizes of map
var data: [UInt8] = []
data = storage.count.encode()
data[0] = data[0] | 0b101_00000
for (key, container) in self.storage {
let keyContainer = _CBOREncoder.SingleValueContainer(codingPath: self.codingPath, userInfo: self.userInfo, options: self.options)
try! keyContainer.encode(key)
data.append(contentsOf: keyContainer.data)
data.append(contentsOf: container.data)
}
return Data(data)
}
}