Skip to content

Commit

Permalink
Merge pull request #10 from g-Off/custom-encoder
Browse files Browse the repository at this point in the history
switching the encoding to being object version aware
  • Loading branch information
g-Off authored Jun 28, 2019
2 parents de01500 + 84d06c7 commit aa649c9
Show file tree
Hide file tree
Showing 46 changed files with 1,114 additions and 1,262 deletions.
27 changes: 0 additions & 27 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,3 @@ playground.xcworkspace
# Packages/
.build/
.swiftpm

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
4 changes: 1 addition & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
language: swift
osx_image: xcode10.2
xcode_project: XcodeProject.xcodeproj
xcode_scheme: XcodeProject
script:
- xcodebuild test -scheme XcodeProject | tee xcodebuild.log | xcpretty && exit ${PIPESTATUS[0]}
- swift test | tee xcodebuild.log | xcpretty && exit ${PIPESTATUS[0]}
16 changes: 0 additions & 16 deletions Makefile

This file was deleted.

31 changes: 31 additions & 0 deletions Sources/XcodeProject/Archiving/Encoder/AnyCodingKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// AnyCodingKey.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2019-06-19.
//

import Foundation

struct AnyCodingKey: CodingKey, Equatable, Hashable {
var stringValue: String
var intValue: Int?

init?(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}

init?(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}

init<Key>(_ base: Key) where Key: CodingKey {
if let intValue = base.intValue {
self.init(intValue: intValue)!
} else {
self.init(stringValue: base.stringValue)!
}
}
}
31 changes: 31 additions & 0 deletions Sources/XcodeProject/Archiving/Encoder/PBXEncoder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// PBXEncoder.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2019-06-18.
//

import Foundation

class PBXObjectEncoder {
static let objectVersionKey = CodingUserInfoKey(rawValue: "objectVersion")!
var objectVersion: ObjectVersion = .xcode93

func encode(_ object: PBXObject) throws -> [String: AnyObject] {
let encoder = _PBXObjectEncoder()
encoder.userInfo = [PBXObjectEncoder.objectVersionKey: objectVersion]
try object.encode(to: encoder)
return encoder.storage.popContainer() as? [String: AnyObject] ?? [:]
}
}

extension Encoder {
var objectVersion: ObjectVersion {
return userInfo[PBXObjectEncoder.objectVersionKey] as? ObjectVersion ?? ObjectVersion.allCases.last!
}

// TODO: better name, but this will allow for encode(to:) function to be able to "smartly" decide to encode id's or objects
var supportsCyclic: Bool {
return self is _PBXObjectEncoder
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// _PBXObjectEncoder+KeyedContainer.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2019-06-19.
//

import Foundation

extension _PBXObjectEncoder {
final class KeyedContainer<Key> where Key: CodingKey {
private let encoder: _PBXObjectEncoder
var codingPath: [CodingKey]

private var container: NSMutableDictionary

init(referencing encoder: _PBXObjectEncoder, codingPath: [CodingKey], wrapping container: NSMutableDictionary) {
self.encoder = encoder
self.codingPath = codingPath
self.container = container
}
}
}

extension _PBXObjectEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
private func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] {
return self.codingPath + [key]
}

func encodeNil(forKey key: Key) throws {
container[key.stringValue] = NSNull()
}

func encode(_ value: String, forKey key: Key) throws {
container[key.stringValue] = NSString(string: value.quotedString)
}

func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
encoder.codingPath.append(key)
defer { encoder.codingPath.removeLast() }
container[key.stringValue] = try encoder.box(value)
}

func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
fatalError()
}

func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
fatalError()
}

func superEncoder() -> Encoder {
fatalError()
}

func superEncoder(forKey key: Key) -> Encoder {
fatalError()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// _PBXObjectEncoder+SingleValueContainer.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2019-06-19.
//

import Foundation

extension _PBXObjectEncoder {
final class SingleValueContainer {
private let encoder: _PBXObjectEncoder
var codingPath: [CodingKey]

init(referencing encoder: _PBXObjectEncoder, codingPath: [CodingKey]) {
self.encoder = encoder
self.codingPath = codingPath
}
}
}

extension _PBXObjectEncoder.SingleValueContainer: SingleValueEncodingContainer {
private func assertCanEncodeNewValue() {
precondition(encoder.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
}

func encodeNil() throws {
encoder.storage.pushValue(NSNull())
}

func encode(_ value: Bool) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: String) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSString(string: value.quotedString))
}

func encode(_ value: Double) throws {
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: "Unsupported type: \(type(of: value))"))
}

func encode(_ value: Float) throws {
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: "Unsupported type: \(type(of: value))"))
}

func encode(_ value: Int) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: Int8) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: Int16) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: Int32) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: Int64) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: UInt) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: UInt8) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: UInt16) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: UInt32) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode(_ value: UInt64) throws {
assertCanEncodeNewValue()
encoder.storage.pushValue(NSNumber(value: value))
}

func encode<T>(_ value: T) throws where T: Encodable {
assertCanEncodeNewValue()
encoder.storage.pushValue(try encoder.box(value))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// _PBXObjectEncoder+UnkeyedContainer.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2019-06-19.
//

import Foundation

extension _PBXObjectEncoder {
final class UnkeyedContainer {
private let encoder: _PBXObjectEncoder
var codingPath: [CodingKey]

private var container: NSMutableArray

init(referencing encoder: _PBXObjectEncoder, codingPath: [CodingKey], wrapping container: NSMutableArray) {
self.encoder = encoder
self.codingPath = codingPath
self.container = container
}
}
}

extension _PBXObjectEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
private var nestedCodingPath: [CodingKey] {
return codingPath + [AnyCodingKey(intValue: count)!]
}

var count: Int {
return container.count
}

func encodeNil() throws {
container.add(NSNull())
}

func encode(_ value: String) throws {
container.add(NSString(string: value.quotedString))
}

func encode<T>(_ value: T) throws where T: Encodable {
encoder.codingPath.append(AnyCodingKey(intValue: count)!)
defer { encoder.codingPath.removeLast() }
container.add(try encoder.box(value))
}

func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
fatalError()
}

func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
fatalError()
}

func superEncoder() -> Encoder {
fatalError()
}
}
Loading

0 comments on commit aa649c9

Please sign in to comment.