Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Marshal mapping #3

Merged
merged 13 commits into from
Apr 12, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ACKReactiveExtensions.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,11 @@ Pod::Spec.new do |s|
realm.dependency 'RealmSwift', '~> 2.1'
realm.source_files = 'ACKReactiveExtensions/Realm/**/*'
end

s.subspec 'Marshal' do |marshal|
marshal.dependency 'ACKReactiveExtensions/Core'
marshal.dependency 'Marshal', '~> 1.2'
marshal.source_files = 'ACKReactiveExtensions/Marshal/**/*'
end

end
128 changes: 128 additions & 0 deletions ACKReactiveExtensions/Marshal/MarshalMapping.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// MarshalMapping.swift
// ACKReactiveExtensions
//
// Created by Jakub Olejník on 06/04/2017.
// Ackee
//

import Result
import Marshal
import ReactiveSwift

/**
* Protocol that allows creation of custom Marshal errors
*/
public protocol MarshalErrorCreatable: Error {

/**
* Create error containing passed `MarshalError`
*
* - parameter marshalError: `MarshalError` which should be wrapped
*/
static func createMarshalError(_ marshalError: MarshalError) -> Self
}

extension MarshalError: MarshalErrorCreatable {
public static func createMarshalError(_ marshalError: MarshalError) -> MarshalError {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be _ marshalError: NSError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't see any reason why? As far as Marshal is throwing MarshalErrors.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aaaaa I see...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now when all errors thrown by the extension are really MarshalErrors this is correct.

return marshalError
}
}

extension SignalProtocol where Value == Any, Error: MarshalErrorCreatable {

/**
* Map value as `Unmarshaling` object
*
* - parameter key: If your objects are contained within dictionary pass the key here
*/
public func mapResponseMarshal<Model>(for key: KeyType? = nil) -> Signal<Model, Error> where Model: Unmarshaling {
return attemptMap { json in
Result {
guard let marshaledJSON = json as? MarshaledObject
else {
assertionFailure("json isn't any of the known MarshaledObject types (Dictionary or Array)")
throw NSError(domain: "", code: 0, userInfo: nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we get rid of this and throw some better error?

}
if let key = key {
return try marshaledJSON.value(for: key)
} else {
return try Model.init(object: marshaledJSON)
}
}
.mapError { Error.createMarshalError($0) }
}
}

/**
* Map value as `Unmarshaling` object
*
* - parameter key: If your objects are contained within dictionary pass the key here
*/
public func mapResponseMarshal<Model>(for key: KeyType? = nil) -> Signal<[Model], Error> where Model: Unmarshaling {
return attemptMap { json in
Result {
if let key = key, let marshaledJSON = json as? MarshaledObject {
return try marshaledJSON.value(for: key)
}
else if let marshaledArray = json as? [MarshaledObject] {
let dummyKey = "dummyKey"
return try [dummyKey: marshaledArray].value(for: dummyKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try marshaledArray.map (Model.init)

}
else {
assertionFailure("json isn't any of the known MarshaledObject types (Dictionary or Array)")
throw NSError(domain: "", code: 0, userInfo: nil)
}
}
.mapError { Error.createMarshalError($0) }
}
}

/**
* Map value as `ValueType`
*
* - parameter key: If your objects are contained within dictionary pass the key here
*/
public func mapResponseMarshal<Model>(for key: KeyType) -> Signal<Model, Error> where Model: ValueType {
return attemptMap { json in
Result {
guard let marshaledJSON = json as? MarshaledObject
else {
assertionFailure("json isn't any of the known MarshaledObject types (Dictionary or Array)")
throw NSError(domain: "", code: 0, userInfo: nil)
}
return try marshaledJSON.value(for: key)
}
.mapError { Error.createMarshalError($0) }
}
}
}

extension SignalProducerProtocol where Value == Any, Error: MarshalErrorCreatable {
/**
* Map value as `Unmarshaling` object
*
* - parameter key: If your objects are contained within dictionary pass the key here
*/
public func mapResponseMarshal<Model>(for key: KeyType? = nil) -> SignalProducer<Model, Error> where Model: Unmarshaling {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change it to forKey key: KeyType? = nil). It's not clear what for: means.

return lift { $0.mapResponseMarshal(for: key) }
}

/**
* Map value as `Unmarshaling` object
*
* - parameter key: If your objects are contained within dictionary pass the key here
*/
public func mapResponseMarshal<Model>(for key: KeyType? = nil) -> SignalProducer<[Model], Error> where Model: Unmarshaling {
return lift { $0.mapResponseMarshal(for: key) }
}

/**
* Map value as `ValueType`
*
* - parameter key: If your objects are contained within dictionary pass the key here
*/
public func mapResponseMarshal<Model>(for key: KeyType) -> SignalProducer<Model, Error> where Model: ValueType {
return lift { $0.mapResponseMarshal(for: key) }
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be also nice to have some test to call the public API

Copy link
Member Author

@olejnjak olejnjak Apr 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean something like this?

4 changes: 4 additions & 0 deletions Example/ACKReactiveExtensions.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
693402381D1296C3004F1FFB /* UIKitExtensionsThreadingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693402371D1296C3004F1FFB /* UIKitExtensionsThreadingSpec.swift */; };
69FDE6FD1E968255004FD0D7 /* MarshalMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69FDE6FC1E968255004FD0D7 /* MarshalMappingTests.swift */; };
93633F05A07E7E137AB05065 /* Pods_ACKReactiveExtensions_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 482304D33E40D8C0EF1F687B /* Pods_ACKReactiveExtensions_Example.framework */; };
ACF37BD01E26CED900FE04FF /* RealmTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACF37BCF1E26CED900FE04FF /* RealmTest.swift */; };
E7AF6B155A6030F53856FC10 /* Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA849E88A474C832B5FE7224 /* Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework */; };
Expand Down Expand Up @@ -44,6 +45,7 @@
607FACE51AFB9204008FA782 /* ACKReactiveExtensions_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ACKReactiveExtensions_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
693402371D1296C3004F1FFB /* UIKitExtensionsThreadingSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitExtensionsThreadingSpec.swift; sourceTree = "<group>"; };
69FDE6FC1E968255004FD0D7 /* MarshalMappingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarshalMappingTests.swift; sourceTree = "<group>"; };
AA849E88A474C832B5FE7224 /* Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
ACF37BCF1E26CED900FE04FF /* RealmTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmTest.swift; sourceTree = "<group>"; };
B3CB8296538D6AF90E03A00A /* Pods-ACKReactiveExtensions_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ACKReactiveExtensions_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ACKReactiveExtensions_Example/Pods-ACKReactiveExtensions_Example.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -129,6 +131,7 @@
607FACE91AFB9204008FA782 /* Supporting Files */,
693402371D1296C3004F1FFB /* UIKitExtensionsThreadingSpec.swift */,
ACF37BCF1E26CED900FE04FF /* RealmTest.swift */,
69FDE6FC1E968255004FD0D7 /* MarshalMappingTests.swift */,
);
path = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -377,6 +380,7 @@
files = (
693402381D1296C3004F1FFB /* UIKitExtensionsThreadingSpec.swift in Sources */,
ACF37BD01E26CED900FE04FF /* RealmTest.swift in Sources */,
69FDE6FD1E968255004FD0D7 /* MarshalMappingTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
1 change: 1 addition & 0 deletions Example/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ target 'ACKReactiveExtensions_Example' do
pod 'ACKReactiveExtensions/SDWebImage', :path => '../'
pod 'ACKReactiveExtensions/WebKit', :path => '../'
pod 'ACKReactiveExtensions/Realm', :path => '../'
pod 'ACKReactiveExtensions/Marshal', :path => '../'

target 'ACKReactiveExtensions_Tests' do
pod 'Quick', '~> 0.10'
Expand Down
15 changes: 11 additions & 4 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ PODS:
- ReactiveCocoa (~> 5.0)
- ACKReactiveExtensions/Core (2.3.0):
- ReactiveCocoa (~> 5.0)
- ACKReactiveExtensions/Marshal (2.3.0):
- ACKReactiveExtensions/Core
- Marshal (~> 1.2)
- ReactiveCocoa (~> 5.0)
- ACKReactiveExtensions/Reachability (2.3.0):
- ACKReactiveExtensions/Core
- Reachability
Expand All @@ -26,8 +30,9 @@ PODS:
- ACKReactiveExtensions/WebKit (2.3.0):
- ACKReactiveExtensions/Core
- ReactiveCocoa (~> 5.0)
- Argo (4.1.1):
- Argo (4.1.2):
- Runes (>= 4.0.0)
- Marshal (1.2.4)
- Nimble (5.1.1)
- Quick (0.10.0)
- Reachability (3.2)
Expand All @@ -49,6 +54,7 @@ PODS:
DEPENDENCIES:
- ACKReactiveExtensions (from `../`)
- ACKReactiveExtensions/Argo (from `../`)
- ACKReactiveExtensions/Marshal (from `../`)
- ACKReactiveExtensions/Reachability (from `../`)
- ACKReactiveExtensions/Realm (from `../`)
- ACKReactiveExtensions/SDWebImage (from `../`)
Expand All @@ -62,8 +68,9 @@ EXTERNAL SOURCES:
:path: "../"

SPEC CHECKSUMS:
ACKReactiveExtensions: c0941143cdc7e350df0a2375224c19d02a55cf9a
Argo: 014ac072f97462bc1a9b83d302edb351488a532f
ACKReactiveExtensions: 78ed5e35371468e9044343f931ca17ab431c6d27
Argo: 5db06502fc1222d83011f574243089dab25202ff
Marshal: 8e04e6624e506921db7143b0bfd83caee03f32d6
Nimble: 415e3aa3267e7bc2c96b05fa814ddea7bb686a29
Quick: 5d290df1c69d5ee2f0729956dcf0fd9a30447eaa
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
Expand All @@ -75,6 +82,6 @@ SPEC CHECKSUMS:
Runes: ff20f163b478ac2c0e18158d6086fd5b1997f983
SDWebImage: 76a6348bdc74eb5a55dd08a091ef298e56b55e41

PODFILE CHECKSUM: 6c1b7d05f93f381c4bd7338de6c376b1606452db
PODFILE CHECKSUM: 45b6f00e1fff1c6f028528ca3b875410a921da66

COCOAPODS: 1.2.0
14 changes: 7 additions & 7 deletions Example/Pods/Argo/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Example/Pods/Argo/Sources/Argo/Types/StandardTypes.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 15 additions & 3 deletions Example/Pods/Local Podspecs/ACKReactiveExtensions.podspec.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 11 additions & 4 deletions Example/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Example/Pods/Marshal/LICENSE.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading