Skip to content

Commit aa649c9

Browse files
authored
Merge pull request #10 from g-Off/custom-encoder
switching the encoding to being object version aware
2 parents de01500 + 84d06c7 commit aa649c9

46 files changed

Lines changed: 1114 additions & 1262 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,30 +37,3 @@ playground.xcworkspace
3737
# Packages/
3838
.build/
3939
.swiftpm
40-
41-
# CocoaPods
42-
#
43-
# We recommend against adding the Pods directory to your .gitignore. However
44-
# you should judge for yourself, the pros and cons are mentioned at:
45-
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
46-
#
47-
# Pods/
48-
49-
# Carthage
50-
#
51-
# Add this line if you want to avoid checking in source code from Carthage dependencies.
52-
# Carthage/Checkouts
53-
54-
Carthage/Build
55-
56-
# fastlane
57-
#
58-
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
59-
# screenshots whenever they are needed.
60-
# For more information about the recommended setup visit:
61-
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
62-
63-
fastlane/report.xml
64-
fastlane/Preview.html
65-
fastlane/screenshots
66-
fastlane/test_output

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
language: swift
22
osx_image: xcode10.2
3-
xcode_project: XcodeProject.xcodeproj
4-
xcode_scheme: XcodeProject
53
script:
6-
- xcodebuild test -scheme XcodeProject | tee xcodebuild.log | xcpretty && exit ${PIPESTATUS[0]}
4+
- swift test | tee xcodebuild.log | xcpretty && exit ${PIPESTATUS[0]}

Makefile

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// AnyCodingKey.swift
3+
// XcodeProject
4+
//
5+
// Created by Geoffrey Foster on 2019-06-19.
6+
//
7+
8+
import Foundation
9+
10+
struct AnyCodingKey: CodingKey, Equatable, Hashable {
11+
var stringValue: String
12+
var intValue: Int?
13+
14+
init?(stringValue: String) {
15+
self.stringValue = stringValue
16+
self.intValue = nil
17+
}
18+
19+
init?(intValue: Int) {
20+
self.stringValue = "\(intValue)"
21+
self.intValue = intValue
22+
}
23+
24+
init<Key>(_ base: Key) where Key: CodingKey {
25+
if let intValue = base.intValue {
26+
self.init(intValue: intValue)!
27+
} else {
28+
self.init(stringValue: base.stringValue)!
29+
}
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// PBXEncoder.swift
3+
// XcodeProject
4+
//
5+
// Created by Geoffrey Foster on 2019-06-18.
6+
//
7+
8+
import Foundation
9+
10+
class PBXObjectEncoder {
11+
static let objectVersionKey = CodingUserInfoKey(rawValue: "objectVersion")!
12+
var objectVersion: ObjectVersion = .xcode93
13+
14+
func encode(_ object: PBXObject) throws -> [String: AnyObject] {
15+
let encoder = _PBXObjectEncoder()
16+
encoder.userInfo = [PBXObjectEncoder.objectVersionKey: objectVersion]
17+
try object.encode(to: encoder)
18+
return encoder.storage.popContainer() as? [String: AnyObject] ?? [:]
19+
}
20+
}
21+
22+
extension Encoder {
23+
var objectVersion: ObjectVersion {
24+
return userInfo[PBXObjectEncoder.objectVersionKey] as? ObjectVersion ?? ObjectVersion.allCases.last!
25+
}
26+
27+
// TODO: better name, but this will allow for encode(to:) function to be able to "smartly" decide to encode id's or objects
28+
var supportsCyclic: Bool {
29+
return self is _PBXObjectEncoder
30+
}
31+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// _PBXObjectEncoder+KeyedContainer.swift
3+
// XcodeProject
4+
//
5+
// Created by Geoffrey Foster on 2019-06-19.
6+
//
7+
8+
import Foundation
9+
10+
extension _PBXObjectEncoder {
11+
final class KeyedContainer<Key> where Key: CodingKey {
12+
private let encoder: _PBXObjectEncoder
13+
var codingPath: [CodingKey]
14+
15+
private var container: NSMutableDictionary
16+
17+
init(referencing encoder: _PBXObjectEncoder, codingPath: [CodingKey], wrapping container: NSMutableDictionary) {
18+
self.encoder = encoder
19+
self.codingPath = codingPath
20+
self.container = container
21+
}
22+
}
23+
}
24+
25+
extension _PBXObjectEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
26+
private func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] {
27+
return self.codingPath + [key]
28+
}
29+
30+
func encodeNil(forKey key: Key) throws {
31+
container[key.stringValue] = NSNull()
32+
}
33+
34+
func encode(_ value: String, forKey key: Key) throws {
35+
container[key.stringValue] = NSString(string: value.quotedString)
36+
}
37+
38+
func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
39+
encoder.codingPath.append(key)
40+
defer { encoder.codingPath.removeLast() }
41+
container[key.stringValue] = try encoder.box(value)
42+
}
43+
44+
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
45+
fatalError()
46+
}
47+
48+
func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
49+
fatalError()
50+
}
51+
52+
func superEncoder() -> Encoder {
53+
fatalError()
54+
}
55+
56+
func superEncoder(forKey key: Key) -> Encoder {
57+
fatalError()
58+
}
59+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// _PBXObjectEncoder+SingleValueContainer.swift
3+
// XcodeProject
4+
//
5+
// Created by Geoffrey Foster on 2019-06-19.
6+
//
7+
8+
import Foundation
9+
10+
extension _PBXObjectEncoder {
11+
final class SingleValueContainer {
12+
private let encoder: _PBXObjectEncoder
13+
var codingPath: [CodingKey]
14+
15+
init(referencing encoder: _PBXObjectEncoder, codingPath: [CodingKey]) {
16+
self.encoder = encoder
17+
self.codingPath = codingPath
18+
}
19+
}
20+
}
21+
22+
extension _PBXObjectEncoder.SingleValueContainer: SingleValueEncodingContainer {
23+
private func assertCanEncodeNewValue() {
24+
precondition(encoder.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
25+
}
26+
27+
func encodeNil() throws {
28+
encoder.storage.pushValue(NSNull())
29+
}
30+
31+
func encode(_ value: Bool) throws {
32+
assertCanEncodeNewValue()
33+
encoder.storage.pushValue(NSNumber(value: value))
34+
}
35+
36+
func encode(_ value: String) throws {
37+
assertCanEncodeNewValue()
38+
encoder.storage.pushValue(NSString(string: value.quotedString))
39+
}
40+
41+
func encode(_ value: Double) throws {
42+
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: "Unsupported type: \(type(of: value))"))
43+
}
44+
45+
func encode(_ value: Float) throws {
46+
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: "Unsupported type: \(type(of: value))"))
47+
}
48+
49+
func encode(_ value: Int) throws {
50+
assertCanEncodeNewValue()
51+
encoder.storage.pushValue(NSNumber(value: value))
52+
}
53+
54+
func encode(_ value: Int8) throws {
55+
assertCanEncodeNewValue()
56+
encoder.storage.pushValue(NSNumber(value: value))
57+
}
58+
59+
func encode(_ value: Int16) throws {
60+
assertCanEncodeNewValue()
61+
encoder.storage.pushValue(NSNumber(value: value))
62+
}
63+
64+
func encode(_ value: Int32) throws {
65+
assertCanEncodeNewValue()
66+
encoder.storage.pushValue(NSNumber(value: value))
67+
}
68+
69+
func encode(_ value: Int64) throws {
70+
assertCanEncodeNewValue()
71+
encoder.storage.pushValue(NSNumber(value: value))
72+
}
73+
74+
func encode(_ value: UInt) throws {
75+
assertCanEncodeNewValue()
76+
encoder.storage.pushValue(NSNumber(value: value))
77+
}
78+
79+
func encode(_ value: UInt8) throws {
80+
assertCanEncodeNewValue()
81+
encoder.storage.pushValue(NSNumber(value: value))
82+
}
83+
84+
func encode(_ value: UInt16) throws {
85+
assertCanEncodeNewValue()
86+
encoder.storage.pushValue(NSNumber(value: value))
87+
}
88+
89+
func encode(_ value: UInt32) throws {
90+
assertCanEncodeNewValue()
91+
encoder.storage.pushValue(NSNumber(value: value))
92+
}
93+
94+
func encode(_ value: UInt64) throws {
95+
assertCanEncodeNewValue()
96+
encoder.storage.pushValue(NSNumber(value: value))
97+
}
98+
99+
func encode<T>(_ value: T) throws where T: Encodable {
100+
assertCanEncodeNewValue()
101+
encoder.storage.pushValue(try encoder.box(value))
102+
}
103+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// _PBXObjectEncoder+UnkeyedContainer.swift
3+
// XcodeProject
4+
//
5+
// Created by Geoffrey Foster on 2019-06-19.
6+
//
7+
8+
import Foundation
9+
10+
extension _PBXObjectEncoder {
11+
final class UnkeyedContainer {
12+
private let encoder: _PBXObjectEncoder
13+
var codingPath: [CodingKey]
14+
15+
private var container: NSMutableArray
16+
17+
init(referencing encoder: _PBXObjectEncoder, codingPath: [CodingKey], wrapping container: NSMutableArray) {
18+
self.encoder = encoder
19+
self.codingPath = codingPath
20+
self.container = container
21+
}
22+
}
23+
}
24+
25+
extension _PBXObjectEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
26+
private var nestedCodingPath: [CodingKey] {
27+
return codingPath + [AnyCodingKey(intValue: count)!]
28+
}
29+
30+
var count: Int {
31+
return container.count
32+
}
33+
34+
func encodeNil() throws {
35+
container.add(NSNull())
36+
}
37+
38+
func encode(_ value: String) throws {
39+
container.add(NSString(string: value.quotedString))
40+
}
41+
42+
func encode<T>(_ value: T) throws where T: Encodable {
43+
encoder.codingPath.append(AnyCodingKey(intValue: count)!)
44+
defer { encoder.codingPath.removeLast() }
45+
container.add(try encoder.box(value))
46+
}
47+
48+
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
49+
fatalError()
50+
}
51+
52+
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
53+
fatalError()
54+
}
55+
56+
func superEncoder() -> Encoder {
57+
fatalError()
58+
}
59+
}

0 commit comments

Comments
 (0)