Unverified Commit e2e37162 authored by Zach Knox's avatar Zach Knox
Browse files

handoff and search actually work now and omg they are so cool

parent 4eb16a58
...@@ -7,7 +7,9 @@ use_frameworks! ...@@ -7,7 +7,9 @@ use_frameworks!
def ios_pods def ios_pods
pod 'RealmSwift' pod 'RealmSwift'
pod 'ObjectMapper', '~> 3.2' #pod 'ObjectMapper', '~> 3.2'
# TEMPORARY BECAUSE Xcode 10
pod 'ObjectMapper', :git => 'https://github.com/alecdoconnor/ObjectMapper.git', :branch => 'Swift-4.2'
pod "ObjectMapper+Realm" pod "ObjectMapper+Realm"
#pod 'Segmentio', '~> 2.1' #pod 'Segmentio', '~> 2.1'
......
...@@ -17,10 +17,20 @@ DEPENDENCIES: ...@@ -17,10 +17,20 @@ DEPENDENCIES:
- Crashlytics - Crashlytics
- DeckTransition (~> 2.0) - DeckTransition (~> 2.0)
- Fabric - Fabric
- ObjectMapper (~> 3.2) - ObjectMapper (from `https://github.com/alecdoconnor/ObjectMapper.git`, branch `Swift-4.2`)
- ObjectMapper+Realm - ObjectMapper+Realm
- RealmSwift - RealmSwift
EXTERNAL SOURCES:
ObjectMapper:
:branch: Swift-4.2
:git: https://github.com/alecdoconnor/ObjectMapper.git
CHECKOUT OPTIONS:
ObjectMapper:
:commit: af7966b567860596fad270bb44b27f495cd8691d
:git: https://github.com/alecdoconnor/ObjectMapper.git
SPEC CHECKSUMS: SPEC CHECKSUMS:
Crashlytics: 0360624eea1c978a743feddb2fb1ef8b37fb7a0d Crashlytics: 0360624eea1c978a743feddb2fb1ef8b37fb7a0d
DeckTransition: 2300694f94fbeca2c103f365dc9dc09ffae14a4f DeckTransition: 2300694f94fbeca2c103f365dc9dc09ffae14a4f
...@@ -30,6 +40,6 @@ SPEC CHECKSUMS: ...@@ -30,6 +40,6 @@ SPEC CHECKSUMS:
Realm: 906be37d52f17f25484ac01643a7f26a9d3bfbd5 Realm: 906be37d52f17f25484ac01643a7f26a9d3bfbd5
RealmSwift: 1c2b6bae3dc55bb87e080ffa96537d71442f6dce RealmSwift: 1c2b6bae3dc55bb87e080ffa96537d71442f6dce
PODFILE CHECKSUM: 999bfe9f7d07d176c0bb5bff060455f38135f947 PODFILE CHECKSUM: f77678c4bb98cdb953f0eb4226354e2455803d42
COCOAPODS: 1.4.0 COCOAPODS: 1.4.0
{
"name": "ObjectMapper",
"version": "3.2.0",
"license": "MIT",
"summary": "JSON Object mapping written in Swift",
"homepage": "https://github.com/Hearst-DD/ObjectMapper",
"authors": {
"Tristan Himmelman": "tristanhimmelman@gmail.com"
},
"source": {
"git": "https://github.com/Hearst-DD/ObjectMapper.git",
"tag": "3.2.0"
},
"platforms": {
"watchos": "2.0",
"ios": "8.0",
"osx": "10.9",
"tvos": "9.0"
},
"swift_version": "4.0",
"requires_arc": true,
"source_files": "Sources/**/*.swift"
}
...@@ -17,10 +17,20 @@ DEPENDENCIES: ...@@ -17,10 +17,20 @@ DEPENDENCIES:
- Crashlytics - Crashlytics
- DeckTransition (~> 2.0) - DeckTransition (~> 2.0)
- Fabric - Fabric
- ObjectMapper (~> 3.2) - ObjectMapper (from `https://github.com/alecdoconnor/ObjectMapper.git`, branch `Swift-4.2`)
- ObjectMapper+Realm - ObjectMapper+Realm
- RealmSwift - RealmSwift
EXTERNAL SOURCES:
ObjectMapper:
:branch: Swift-4.2
:git: https://github.com/alecdoconnor/ObjectMapper.git
CHECKOUT OPTIONS:
ObjectMapper:
:commit: af7966b567860596fad270bb44b27f495cd8691d
:git: https://github.com/alecdoconnor/ObjectMapper.git
SPEC CHECKSUMS: SPEC CHECKSUMS:
Crashlytics: 0360624eea1c978a743feddb2fb1ef8b37fb7a0d Crashlytics: 0360624eea1c978a743feddb2fb1ef8b37fb7a0d
DeckTransition: 2300694f94fbeca2c103f365dc9dc09ffae14a4f DeckTransition: 2300694f94fbeca2c103f365dc9dc09ffae14a4f
...@@ -30,6 +40,6 @@ SPEC CHECKSUMS: ...@@ -30,6 +40,6 @@ SPEC CHECKSUMS:
Realm: 906be37d52f17f25484ac01643a7f26a9d3bfbd5 Realm: 906be37d52f17f25484ac01643a7f26a9d3bfbd5
RealmSwift: 1c2b6bae3dc55bb87e080ffa96537d71442f6dce RealmSwift: 1c2b6bae3dc55bb87e080ffa96537d71442f6dce
PODFILE CHECKSUM: 999bfe9f7d07d176c0bb5bff060455f38135f947 PODFILE CHECKSUM: f77678c4bb98cdb953f0eb4226354e2455803d42
COCOAPODS: 1.4.0 COCOAPODS: 1.4.0
...@@ -31,11 +31,6 @@ public func >>> <T: RawRepresentable>(left: T?, right: Map) { ...@@ -31,11 +31,6 @@ public func >>> <T: RawRepresentable>(left: T?, right: Map) {
} }
/// Implicitly Unwrapped Optional Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T!, right: Map) {
left <- (right, EnumTransform())
}
// MARK:- Arrays of Raw Representable type // MARK:- Arrays of Raw Representable type
/// Array of Raw Representable object /// Array of Raw Representable object
...@@ -58,11 +53,6 @@ public func >>> <T: RawRepresentable>(left: [T]?, right: Map) { ...@@ -58,11 +53,6 @@ public func >>> <T: RawRepresentable>(left: [T]?, right: Map) {
} }
/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T]!, right: Map) {
left <- (right, EnumTransform())
}
// MARK:- Dictionaries of Raw Representable type // MARK:- Dictionaries of Raw Representable type
/// Dictionary of Raw Representable object /// Dictionary of Raw Representable object
...@@ -83,9 +73,3 @@ public func <- <T: RawRepresentable>(left: inout [String: T]?, right: Map) { ...@@ -83,9 +73,3 @@ public func <- <T: RawRepresentable>(left: inout [String: T]?, right: Map) {
public func >>> <T: RawRepresentable>(left: [String: T]?, right: Map) { public func >>> <T: RawRepresentable>(left: [String: T]?, right: Map) {
left >>> (right, EnumTransform()) left >>> (right, EnumTransform())
} }
/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T]!, right: Map) {
left <- (right, EnumTransform())
}
...@@ -40,11 +40,6 @@ internal final class FromJSON { ...@@ -40,11 +40,6 @@ internal final class FromJSON {
field = object field = object
} }
/// Implicitly unwrapped optional basic type
class func optionalBasicType<FieldType>(_ field: inout FieldType!, object: FieldType?) {
field = object
}
/// Mappable object /// Mappable object
class func object<N: BaseMappable>(_ field: inout N, map: Map) { class func object<N: BaseMappable>(_ field: inout N, map: Map) {
if map.toObject { if map.toObject {
...@@ -64,15 +59,6 @@ internal final class FromJSON { ...@@ -64,15 +59,6 @@ internal final class FromJSON {
} }
} }
/// Implicitly unwrapped Optional Mappable Object
class func optionalObject<N: BaseMappable>(_ field: inout N!, map: Map) {
if let f = field , map.toObject && map.currentValue != nil {
field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: f)
} else {
field = Mapper(context: map.context).map(JSONObject: map.currentValue)
}
}
/// mappable object array /// mappable object array
class func objectArray<N: BaseMappable>(_ field: inout Array<N>, map: Map) { class func objectArray<N: BaseMappable>(_ field: inout Array<N>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapArray(JSONObject: map.currentValue) { if let objects = Mapper<N>(context: map.context).mapArray(JSONObject: map.currentValue) {
...@@ -90,15 +76,6 @@ internal final class FromJSON { ...@@ -90,15 +76,6 @@ internal final class FromJSON {
} }
} }
/// Implicitly unwrapped optional mappable object array
class func optionalObjectArray<N: BaseMappable>(_ field: inout Array<N>!, map: Map) {
if let objects: Array<N> = Mapper(context: map.context).mapArray(JSONObject: map.currentValue) {
field = objects
} else {
field = nil
}
}
/// mappable object array /// mappable object array
class func twoDimensionalObjectArray<N: BaseMappable>(_ field: inout Array<Array<N>>, map: Map) { class func twoDimensionalObjectArray<N: BaseMappable>(_ field: inout Array<Array<N>>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) { if let objects = Mapper<N>(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) {
...@@ -111,11 +88,6 @@ internal final class FromJSON { ...@@ -111,11 +88,6 @@ internal final class FromJSON {
field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue)
} }
/// Implicitly unwrapped optional 2 dimentional mappable object array
class func optionalTwoDimensionalObjectArray<N: BaseMappable>(_ field: inout Array<Array<N>>!, map: Map) {
field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue)
}
/// Dctionary containing Mappable objects /// Dctionary containing Mappable objects
class func objectDictionary<N: BaseMappable>(_ field: inout Dictionary<String, N>, map: Map) { class func objectDictionary<N: BaseMappable>(_ field: inout Dictionary<String, N>, map: Map) {
if map.toObject { if map.toObject {
...@@ -136,15 +108,6 @@ internal final class FromJSON { ...@@ -136,15 +108,6 @@ internal final class FromJSON {
} }
} }
/// Implicitly unwrapped Dictionary containing Mappable objects
class func optionalObjectDictionary<N: BaseMappable>(_ field: inout Dictionary<String, N>!, map: Map) {
if let f = field , map.toObject && map.currentValue != nil {
field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: f)
} else {
field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue)
}
}
/// Dictionary containing Array of Mappable objects /// Dictionary containing Array of Mappable objects
class func objectDictionaryOfArrays<N: BaseMappable>(_ field: inout Dictionary<String, [N]>, map: Map) { class func objectDictionaryOfArrays<N: BaseMappable>(_ field: inout Dictionary<String, [N]>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) { if let objects = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) {
...@@ -157,11 +120,6 @@ internal final class FromJSON { ...@@ -157,11 +120,6 @@ internal final class FromJSON {
field = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) field = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue)
} }
/// Implicitly unwrapped Dictionary containing Array of Mappable objects
class func optionalObjectDictionaryOfArrays<N: BaseMappable>(_ field: inout Dictionary<String, [N]>!, map: Map) {
field = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue)
}
/// mappable object Set /// mappable object Set
class func objectSet<N: BaseMappable>(_ field: inout Set<N>, map: Map) { class func objectSet<N: BaseMappable>(_ field: inout Set<N>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapSet(JSONObject: map.currentValue) { if let objects = Mapper<N>(context: map.context).mapSet(JSONObject: map.currentValue) {
...@@ -173,9 +131,4 @@ internal final class FromJSON { ...@@ -173,9 +131,4 @@ internal final class FromJSON {
class func optionalObjectSet<N: BaseMappable>(_ field: inout Set<N>?, map: Map) { class func optionalObjectSet<N: BaseMappable>(_ field: inout Set<N>?, map: Map) {
field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue) field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue)
} }
/// Implicitly unwrapped optional mappable object array
class func optionalObjectSet<N: BaseMappable>(_ field: inout Set<N>!, map: Map) {
field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue)
}
} }
...@@ -214,7 +214,7 @@ public extension Mapper where N: ImmutableMappable { ...@@ -214,7 +214,7 @@ public extension Mapper where N: ImmutableMappable {
// MARK: Array mapping functions // MARK: Array mapping functions
public func mapArray(JSONArray: [[String: Any]]) throws -> [N] { public func mapArray(JSONArray: [[String: Any]]) throws -> [N] {
return try JSONArray.flatMap(mapOrFail) return try JSONArray.compactMap(mapOrFail)
} }
public func mapArray(JSONString: String) throws -> [N] { public func mapArray(JSONString: String) throws -> [N] {
......
...@@ -34,18 +34,6 @@ public func <- <T: SignedInteger>(left: inout T?, right: Map) { ...@@ -34,18 +34,6 @@ public func <- <T: SignedInteger>(left: inout T?, right: Map) {
} }
} }
/// ImplicitlyUnwrappedOptional SignedInteger mapping
public func <- <T: SignedInteger>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T! = toSignedInteger(right.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
// MARK: - Unsigned Integer // MARK: - Unsigned Integer
...@@ -74,18 +62,6 @@ public func <- <T: UnsignedInteger>(left: inout T?, right: Map) { ...@@ -74,18 +62,6 @@ public func <- <T: UnsignedInteger>(left: inout T?, right: Map) {
} }
} }
/// ImplicitlyUnwrappedOptional UnsignedInteger mapping
public func <- <T: UnsignedInteger>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T! = toUnsignedInteger(right.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
// MARK: - Casting Utils // MARK: - Casting Utils
/// Convert any value to `SignedInteger`. /// Convert any value to `SignedInteger`.
......
...@@ -124,14 +124,14 @@ public final class Map { ...@@ -124,14 +124,14 @@ public final class Map {
public func value<T>() -> T? { public func value<T>() -> T? {
let value = currentValue as? T let value = currentValue as? T
// Swift 4.1 breaks Float casting from `NSNumber`. So Added extra checks for `Flaot` `[Float]` and `[String:Float]` // Swift 4.1 breaks Float casting from `NSNumber`. So Added extra checks for `Float` `[Float]` and `[String:Float]`
if value == nil && T.self == Float.self { if value == nil && T.self == Float.self {
if let v = currentValue as? NSNumber { if let v = currentValue as? NSNumber {
return v.floatValue as? T return v.floatValue as? T
} }
} else if value == nil && T.self == [Float].self { } else if value == nil && T.self == [Float].self {
if let v = currentValue as? [Double] { if let v = currentValue as? [Double] {
return v.flatMap{ Float($0) } as? T return v.compactMap{ Float($0) } as? T
} }
} else if value == nil && T.self == [String:Float].self { } else if value == nil && T.self == [String:Float].self {
if let v = currentValue as? [String:Double] { if let v = currentValue as? [String:Double] {
......
...@@ -118,8 +118,6 @@ public final class Mapper<N: BaseMappable> { ...@@ -118,8 +118,6 @@ public final class Mapper<N: BaseMappable> {
exception = NSException(name: .init(rawValue: "ImmutableMappableError"), reason: error.localizedDescription, userInfo: nil) exception = NSException(name: .init(rawValue: "ImmutableMappableError"), reason: error.localizedDescription, userInfo: nil)
} }
exception.raise() exception.raise()
#else
NSLog("\(error)")
#endif #endif
} }
} else { } else {
...@@ -427,7 +425,7 @@ extension Mapper where N: Hashable { ...@@ -427,7 +425,7 @@ extension Mapper where N: Hashable {
/// Maps an Set of JSON dictionary to an array of Mappable objects /// Maps an Set of JSON dictionary to an array of Mappable objects
public func mapSet(JSONArray: [[String: Any]]) -> Set<N> { public func mapSet(JSONArray: [[String: Any]]) -> Set<N> {
// map every element in JSON array to type N // map every element in JSON array to type N
return Set(JSONArray.flatMap(map)) return Set(JSONArray.compactMap(map))
} }
///Maps a Set of Objects to a Set of JSON dictionaries [[String : Any]] ///Maps a Set of Objects to a Set of JSON dictionaries [[String : Any]]
......
...@@ -75,18 +75,6 @@ public func >>> <T>(left: T?, right: Map) { ...@@ -75,18 +75,6 @@ public func >>> <T>(left: T?, right: Map) {
} }
} }
/// Implicitly unwrapped optional object of basic type
public func <- <T>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalBasicType(&left, object: right.value())
case .toJSON:
left >>> right
default: ()
}
}
// MARK:- Mappable Objects - <T: BaseMappable> // MARK:- Mappable Objects - <T: BaseMappable>
/// Object conforming to Mappable /// Object conforming to Mappable
...@@ -123,18 +111,6 @@ public func >>> <T: BaseMappable>(left: T?, right: Map) { ...@@ -123,18 +111,6 @@ public func >>> <T: BaseMappable>(left: T?, right: Map) {
} }
} }
/// Implicitly unwrapped optional Mappable objects
public func <- <T: BaseMappable>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObject(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
// MARK:- Dictionary of Mappable objects - Dictionary<String, T: BaseMappable> // MARK:- Dictionary of Mappable objects - Dictionary<String, T: BaseMappable>
/// Dictionary of Mappable objects <String, T: Mappable> /// Dictionary of Mappable objects <String, T: Mappable>
...@@ -172,18 +148,6 @@ public func >>> <T: BaseMappable>(left: Dictionary<String, T>?, right: Map) { ...@@ -172,18 +148,6 @@ public func >>> <T: BaseMappable>(left: Dictionary<String, T>?, right: Map) {
} }
} }
/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectDictionary(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
/// Dictionary of Mappable objects <String, T: Mappable> /// Dictionary of Mappable objects <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, [T]>, right: Map) { public func <- <T: BaseMappable>(left: inout Dictionary<String, [T]>, right: Map) {
switch right.mappingType { switch right.mappingType {
...@@ -218,18 +182,6 @@ public func >>> <T: BaseMappable>(left: Dictionary<String, [T]>?, right: Map) { ...@@ -218,18 +182,6 @@ public func >>> <T: BaseMappable>(left: Dictionary<String, [T]>?, right: Map) {
} }
} }
/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, [T]>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectDictionaryOfArrays(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
// MARK:- Array of Mappable objects - Array<T: BaseMappable> // MARK:- Array of Mappable objects - Array<T: BaseMappable>
/// Array of Mappable objects /// Array of Mappable objects
...@@ -266,18 +218,6 @@ public func >>> <T: BaseMappable>(left: Array<T>?, right: Map) { ...@@ -266,18 +218,6 @@ public func >>> <T: BaseMappable>(left: Array<T>?, right: Map) {
} }
} }
/// Implicitly unwrapped Optional array of Mappable objects
public func <- <T: BaseMappable>(left: inout Array<T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
// MARK:- Array of Array of Mappable objects - Array<Array<T: BaseMappable>> // MARK:- Array of Array of Mappable objects - Array<Array<T: BaseMappable>>
/// Array of Array Mappable objects /// Array of Array Mappable objects
...@@ -315,18 +255,6 @@ public func >>> <T: BaseMappable>(left: Array<Array<T>>?, right: Map) { ...@@ -315,18 +255,6 @@ public func >>> <T: BaseMappable>(left: Array<Array<T>>?, right: Map) {
} }
} }
/// Implicitly unwrapped Optional array of Mappable objects
public func <- <T: BaseMappable>(left: inout Array<Array<T>>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalTwoDimensionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
// MARK:- Set of Mappable objects - Set<T: BaseMappable> // MARK:- Set of Mappable objects - Set<T: BaseMappable>
/// Set of Mappable objects /// Set of Mappable objects
...@@ -363,15 +291,3 @@ public func >>> <T: BaseMappable>(left: Set<T>?, right: Map) { ...@@ -363,15 +291,3 @@ public func >>> <T: BaseMappable>(left: Set<T>?, right: Map) {
ToJSON.optionalObjectSet(left, map: right) ToJSON.optionalObjectSet(left, map: right)
} }
} }
/// Implicitly unwrapped Optional Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectSet(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
...@@ -53,20 +53,6 @@ public func >>> <Transform: TransformType>(left: Transform.Object?, right: (Map, ...@@ -53,20 +53,6 @@ public func >>> <Transform: TransformType>(left: Transform.Object?, right: (Map,
} }
} }
/// Implicitly unwrapped optional object of basic type with Transform
public func <- <Transform: TransformType>(left: inout Transform.Object!, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value = transform.transformFromJSON(map.currentValue)
FromJSON.optionalBasicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
/// Array of Basic type with Transform /// Array of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [Transform.Object], right: (Map, Transform)) { public func <- <Transform: TransformType>(left: inout [Transform.Object], right: (Map, Transform)) {
let (map, transform) = right let (map, transform) = right
...@@ -110,20 +96,6 @@ public func >>> <Transform: TransformType>(left: [Transform.Object]?, right: (Ma ...@@ -110,20 +96,6 @@ public func >>> <Transform: TransformType>(left: