You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

709 lines
25 KiB

  1. //
  2. // TransformOperators.swift
  3. // ObjectMapper
  4. //
  5. // Created by Tristan Himmelman on 2016-09-26.
  6. //
  7. // The MIT License (MIT)
  8. //
  9. // Copyright (c) 2014-2018 Tristan Himmelman
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining a copy
  12. // of this software and associated documentation files (the "Software"), to deal
  13. // in the Software without restriction, including without limitation the rights
  14. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. // copies of the Software, and to permit persons to whom the Software is
  16. // furnished to do so, subject to the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be included in
  19. // all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. // THE SOFTWARE.
  28. import Foundation
  29. // MARK:- Transforms
  30. /// Object of Basic type with Transform
  31. public func <- <Transform: TransformType>(left: inout Transform.Object, right: (Map, Transform)) {
  32. let (map, transform) = right
  33. switch map.mappingType {
  34. case .fromJSON where map.isKeyPresent:
  35. let value = transform.transformFromJSON(map.currentValue)
  36. FromJSON.basicType(&left, object: value)
  37. case .toJSON:
  38. left >>> right
  39. default: ()
  40. }
  41. }
  42. public func >>> <Transform: TransformType>(left: Transform.Object, right: (Map, Transform)) {
  43. let (map, transform) = right
  44. if map.mappingType == .toJSON {
  45. let value: Transform.JSON? = transform.transformToJSON(left)
  46. ToJSON.optionalBasicType(value, map: map)
  47. }
  48. }
  49. /// Optional object of basic type with Transform
  50. public func <- <Transform: TransformType>(left: inout Transform.Object?, right: (Map, Transform)) {
  51. let (map, transform) = right
  52. switch map.mappingType {
  53. case .fromJSON where map.isKeyPresent:
  54. let value = transform.transformFromJSON(map.currentValue)
  55. FromJSON.optionalBasicType(&left, object: value)
  56. case .toJSON:
  57. left >>> right
  58. default: ()
  59. }
  60. }
  61. public func >>> <Transform: TransformType>(left: Transform.Object?, right: (Map, Transform)) {
  62. let (map, transform) = right
  63. if map.mappingType == .toJSON {
  64. let value: Transform.JSON? = transform.transformToJSON(left)
  65. ToJSON.optionalBasicType(value, map: map)
  66. }
  67. }
  68. // Code targeting the Swift 4.1 compiler and below.
  69. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  70. /// Implicitly unwrapped optional object of basic type with Transform
  71. public func <- <Transform: TransformType>(left: inout Transform.Object!, right: (Map, Transform)) {
  72. let (map, transform) = right
  73. switch map.mappingType {
  74. case .fromJSON where map.isKeyPresent:
  75. let value = transform.transformFromJSON(map.currentValue)
  76. FromJSON.optionalBasicType(&left, object: value)
  77. case .toJSON:
  78. left >>> right
  79. default: ()
  80. }
  81. }
  82. #endif
  83. /// Array of Basic type with Transform
  84. public func <- <Transform: TransformType>(left: inout [Transform.Object], right: (Map, Transform)) {
  85. let (map, transform) = right
  86. switch map.mappingType {
  87. case .fromJSON where map.isKeyPresent:
  88. let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
  89. FromJSON.basicType(&left, object: values)
  90. case .toJSON:
  91. left >>> right
  92. default: ()
  93. }
  94. }
  95. public func >>> <Transform: TransformType>(left: [Transform.Object], right: (Map, Transform)) {
  96. let (map, transform) = right
  97. if map.mappingType == .toJSON{
  98. let values = toJSONArrayWithTransform(left, transform: transform)
  99. ToJSON.optionalBasicType(values, map: map)
  100. }
  101. }
  102. /// Optional array of Basic type with Transform
  103. public func <- <Transform: TransformType>(left: inout [Transform.Object]?, right: (Map, Transform)) {
  104. let (map, transform) = right
  105. switch map.mappingType {
  106. case .fromJSON where map.isKeyPresent:
  107. let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
  108. FromJSON.optionalBasicType(&left, object: values)
  109. case .toJSON:
  110. left >>> right
  111. default: ()
  112. }
  113. }
  114. public func >>> <Transform: TransformType>(left: [Transform.Object]?, right: (Map, Transform)) {
  115. let (map, transform) = right
  116. if map.mappingType == .toJSON {
  117. let values = toJSONArrayWithTransform(left, transform: transform)
  118. ToJSON.optionalBasicType(values, map: map)
  119. }
  120. }
  121. // Code targeting the Swift 4.1 compiler and below.
  122. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  123. /// Implicitly unwrapped optional array of Basic type with Transform
  124. public func <- <Transform: TransformType>(left: inout [Transform.Object]!, right: (Map, Transform)) {
  125. let (map, transform) = right
  126. switch map.mappingType {
  127. case .fromJSON where map.isKeyPresent:
  128. let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
  129. FromJSON.optionalBasicType(&left, object: values)
  130. case .toJSON:
  131. left >>> right
  132. default: ()
  133. }
  134. }
  135. #endif
  136. /// Dictionary of Basic type with Transform
  137. public func <- <Transform: TransformType>(left: inout [String: Transform.Object], right: (Map, Transform)) {
  138. let (map, transform) = right
  139. switch map.mappingType {
  140. case .fromJSON where map.isKeyPresent:
  141. let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
  142. FromJSON.basicType(&left, object: values)
  143. case .toJSON:
  144. left >>> right
  145. default: ()
  146. }
  147. }
  148. public func >>> <Transform: TransformType>(left: [String: Transform.Object], right: (Map, Transform)) {
  149. let (map, transform) = right
  150. if map.mappingType == . toJSON {
  151. let values = toJSONDictionaryWithTransform(left, transform: transform)
  152. ToJSON.optionalBasicType(values, map: map)
  153. }
  154. }
  155. /// Optional dictionary of Basic type with Transform
  156. public func <- <Transform: TransformType>(left: inout [String: Transform.Object]?, right: (Map, Transform)) {
  157. let (map, transform) = right
  158. switch map.mappingType {
  159. case .fromJSON where map.isKeyPresent:
  160. let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
  161. FromJSON.optionalBasicType(&left, object: values)
  162. case .toJSON:
  163. left >>> right
  164. default: ()
  165. }
  166. }
  167. public func >>> <Transform: TransformType>(left: [String: Transform.Object]?, right: (Map, Transform)) {
  168. let (map, transform) = right
  169. if map.mappingType == .toJSON {
  170. let values = toJSONDictionaryWithTransform(left, transform: transform)
  171. ToJSON.optionalBasicType(values, map: map)
  172. }
  173. }
  174. // Code targeting the Swift 4.1 compiler and below.
  175. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  176. /// Implicitly unwrapped optional dictionary of Basic type with Transform
  177. public func <- <Transform: TransformType>(left: inout [String: Transform.Object]!, right: (Map, Transform)) {
  178. let (map, transform) = right
  179. switch map.mappingType {
  180. case .fromJSON where map.isKeyPresent:
  181. let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
  182. FromJSON.optionalBasicType(&left, object: values)
  183. case .toJSON:
  184. left >>> right
  185. default: ()
  186. }
  187. }
  188. #endif
  189. // MARK:- Transforms of Mappable Objects - <T: BaseMappable>
  190. /// Object conforming to Mappable that have transforms
  191. public func <- <Transform: TransformType>(left: inout Transform.Object, right: (Map, Transform)) where Transform.Object: BaseMappable {
  192. let (map, transform) = right
  193. switch map.mappingType {
  194. case .fromJSON where map.isKeyPresent:
  195. let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
  196. FromJSON.basicType(&left, object: value)
  197. case .toJSON:
  198. left >>> right
  199. default: ()
  200. }
  201. }
  202. public func >>> <Transform: TransformType>(left: Transform.Object, right: (Map, Transform)) where Transform.Object: BaseMappable {
  203. let (map, transform) = right
  204. if map.mappingType == .toJSON {
  205. let value: Transform.JSON? = transform.transformToJSON(left)
  206. ToJSON.optionalBasicType(value, map: map)
  207. }
  208. }
  209. /// Optional Mappable objects that have transforms
  210. public func <- <Transform: TransformType>(left: inout Transform.Object?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  211. let (map, transform) = right
  212. switch map.mappingType {
  213. case .fromJSON where map.isKeyPresent:
  214. let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
  215. FromJSON.optionalBasicType(&left, object: value)
  216. case .toJSON:
  217. left >>> right
  218. default: ()
  219. }
  220. }
  221. public func >>> <Transform: TransformType>(left: Transform.Object?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  222. let (map, transform) = right
  223. if map.mappingType == .toJSON{
  224. let value: Transform.JSON? = transform.transformToJSON(left)
  225. ToJSON.optionalBasicType(value, map: map)
  226. }
  227. }
  228. // Code targeting the Swift 4.1 compiler and below.
  229. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  230. /// Implicitly unwrapped optional Mappable objects that have transforms
  231. public func <- <Transform: TransformType>(left: inout Transform.Object!, right: (Map, Transform)) where Transform.Object: BaseMappable {
  232. let (map, transform) = right
  233. switch map.mappingType {
  234. case .fromJSON where map.isKeyPresent:
  235. let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
  236. FromJSON.optionalBasicType(&left, object: value)
  237. case .toJSON:
  238. left >>> right
  239. default: ()
  240. }
  241. }
  242. #endif
  243. // MARK:- Dictionary of Mappable objects with a transform - Dictionary<String, T: BaseMappable>
  244. /// Dictionary of Mappable objects <String, T: Mappable> with a transform
  245. public func <- <Transform: TransformType>(left: inout Dictionary<String, Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  246. let (map, transform) = right
  247. if map.mappingType == .fromJSON && map.isKeyPresent,
  248. let object = map.currentValue as? [String: Any] {
  249. let value = fromJSONDictionaryWithTransform(object as Any?, transform: transform) ?? left
  250. FromJSON.basicType(&left, object: value)
  251. } else if map.mappingType == .toJSON {
  252. left >>> right
  253. }
  254. }
  255. public func >>> <Transform: TransformType>(left: Dictionary<String, Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  256. let (map, transform) = right
  257. if map.mappingType == .toJSON {
  258. let value = toJSONDictionaryWithTransform(left, transform: transform)
  259. ToJSON.basicType(value, map: map)
  260. }
  261. }
  262. /// Optional Dictionary of Mappable object <String, T: Mappable> with a transform
  263. public func <- <Transform: TransformType>(left: inout Dictionary<String, Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  264. let (map, transform) = right
  265. if map.mappingType == .fromJSON && map.isKeyPresent, let object = map.currentValue as? [String : Any]{
  266. let value = fromJSONDictionaryWithTransform(object as Any?, transform: transform) ?? left
  267. FromJSON.optionalBasicType(&left, object: value)
  268. } else if map.mappingType == .toJSON {
  269. left >>> right
  270. }
  271. }
  272. public func >>> <Transform: TransformType>(left: Dictionary<String, Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  273. let (map, transform) = right
  274. if map.mappingType == .toJSON {
  275. let value = toJSONDictionaryWithTransform(left, transform: transform)
  276. ToJSON.optionalBasicType(value, map: map)
  277. }
  278. }
  279. // Code targeting the Swift 4.1 compiler and below.
  280. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  281. /// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable> with a transform
  282. public func <- <Transform: TransformType>(left: inout Dictionary<String, Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
  283. let (map, transform) = right
  284. if map.mappingType == .fromJSON && map.isKeyPresent, let dictionary = map.currentValue as? [String : Any]{
  285. let transformedDictionary = fromJSONDictionaryWithTransform(dictionary as Any?, transform: transform) ?? left
  286. FromJSON.optionalBasicType(&left, object: transformedDictionary)
  287. } else if map.mappingType == .toJSON {
  288. left >>> right
  289. }
  290. }
  291. #endif
  292. /// Dictionary of Mappable objects <String, T: Mappable> with a transform
  293. public func <- <Transform: TransformType>(left: inout Dictionary<String, [Transform.Object]>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  294. let (map, transform) = right
  295. if let dictionary = map.currentValue as? [String : [Any]], map.mappingType == .fromJSON && map.isKeyPresent {
  296. let transformedDictionary = dictionary.map { (arg: (key: String, values: [Any])) -> (String, [Transform.Object]) in
  297. let (key, values) = arg
  298. if let jsonArray = fromJSONArrayWithTransform(values, transform: transform) {
  299. return (key, jsonArray)
  300. }
  301. if let leftValue = left[key] {
  302. return (key, leftValue)
  303. }
  304. return (key, [])
  305. }
  306. FromJSON.basicType(&left, object: transformedDictionary)
  307. } else if map.mappingType == .toJSON {
  308. left >>> right
  309. }
  310. }
  311. public func >>> <Transform: TransformType>(left: Dictionary<String, [Transform.Object]>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  312. let (map, transform) = right
  313. if map.mappingType == .toJSON {
  314. let transformedDictionary = left.map { (arg: (key: String, value: [Transform.Object])) in
  315. return (arg.key, toJSONArrayWithTransform(arg.value, transform: transform) ?? [])
  316. }
  317. ToJSON.basicType(transformedDictionary, map: map)
  318. }
  319. }
  320. /// Optional Dictionary of Mappable object <String, T: Mappable> with a transform
  321. public func <- <Transform: TransformType>(left: inout Dictionary<String, [Transform.Object]>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  322. let (map, transform) = right
  323. if let dictionary = map.currentValue as? [String : [Any]], map.mappingType == .fromJSON && map.isKeyPresent {
  324. let transformedDictionary = dictionary.map { (arg: (key: String, values: [Any])) -> (String, [Transform.Object]) in
  325. let (key, values) = arg
  326. if let jsonArray = fromJSONArrayWithTransform(values, transform: transform) {
  327. return (key, jsonArray)
  328. }
  329. if let leftValue = left?[key] {
  330. return (key, leftValue)
  331. }
  332. return (key, [])
  333. }
  334. FromJSON.optionalBasicType(&left, object: transformedDictionary)
  335. } else if map.mappingType == .toJSON {
  336. left >>> right
  337. }
  338. }
  339. public func >>> <Transform: TransformType>(left: Dictionary<String, [Transform.Object]>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  340. let (map, transform) = right
  341. if map.mappingType == .toJSON {
  342. let transformedDictionary = left?.map { (arg: (key: String, values: [Transform.Object])) in
  343. return (arg.key, toJSONArrayWithTransform(arg.values, transform: transform) ?? [])
  344. }
  345. ToJSON.optionalBasicType(transformedDictionary, map: map)
  346. }
  347. }
  348. // Code targeting the Swift 4.1 compiler and below.
  349. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  350. /// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable> with a transform
  351. public func <- <Transform: TransformType>(left: inout Dictionary<String, [Transform.Object]>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
  352. let (map, transform) = right
  353. if let dictionary = map.currentValue as? [String : [Any]], map.mappingType == .fromJSON && map.isKeyPresent {
  354. let transformedDictionary = dictionary.map { (arg: (key: String, values: [Any])) -> (String, [Transform.Object]) in
  355. let (key, values) = arg
  356. if let jsonArray = fromJSONArrayWithTransform(values, transform: transform) {
  357. return (key, jsonArray)
  358. }
  359. if let leftValue = left?[key] {
  360. return (key, leftValue)
  361. }
  362. return (key, [])
  363. }
  364. FromJSON.optionalBasicType(&left, object: transformedDictionary)
  365. } else if map.mappingType == .toJSON {
  366. left >>> right
  367. }
  368. }
  369. #endif
  370. // MARK:- Array of Mappable objects with transforms - Array<T: BaseMappable>
  371. /// Array of Mappable objects
  372. public func <- <Transform: TransformType>(left: inout Array<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  373. let (map, transform) = right
  374. switch map.mappingType {
  375. case .fromJSON where map.isKeyPresent:
  376. if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
  377. FromJSON.basicType(&left, object: transformedValues)
  378. }
  379. case .toJSON:
  380. left >>> right
  381. default: ()
  382. }
  383. }
  384. public func >>> <Transform: TransformType>(left: Array<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  385. let (map, transform) = right
  386. if map.mappingType == .toJSON {
  387. let transformedValues = toJSONArrayWithTransform(left, transform: transform)
  388. ToJSON.optionalBasicType(transformedValues, map: map)
  389. }
  390. }
  391. /// Optional array of Mappable objects
  392. public func <- <Transform: TransformType>(left: inout Array<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  393. let (map, transform) = right
  394. switch map.mappingType {
  395. case .fromJSON where map.isKeyPresent:
  396. let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform)
  397. FromJSON.optionalBasicType(&left, object: transformedValues)
  398. case .toJSON:
  399. left >>> right
  400. default: ()
  401. }
  402. }
  403. public func >>> <Transform: TransformType>(left: Array<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  404. let (map, transform) = right
  405. if map.mappingType == .toJSON {
  406. let transformedValues = toJSONArrayWithTransform(left, transform: transform)
  407. ToJSON.optionalBasicType(transformedValues, map: map)
  408. }
  409. }
  410. // Code targeting the Swift 4.1 compiler and below.
  411. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  412. /// Implicitly unwrapped Optional array of Mappable objects
  413. public func <- <Transform: TransformType>(left: inout Array<Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
  414. let (map, transform) = right
  415. switch map.mappingType {
  416. case .fromJSON where map.isKeyPresent:
  417. let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform)
  418. FromJSON.optionalBasicType(&left, object: transformedValues)
  419. case .toJSON:
  420. left >>> right
  421. default: ()
  422. }
  423. }
  424. #endif
  425. // MARK:- Array of Array of objects - Array<Array<T>>> with transforms
  426. /// Array of Array of objects with transform
  427. public func <- <Transform: TransformType>(left: inout [[Transform.Object]], right: (Map, Transform)) {
  428. let (map, transform) = right
  429. switch map.mappingType {
  430. case .toJSON:
  431. left >>> right
  432. case .fromJSON where map.isKeyPresent:
  433. guard let original2DArray = map.currentValue as? [[Any]] else { break }
  434. #if swift(>=4.1)
  435. let transformed2DArray = original2DArray.compactMap { values in
  436. fromJSONArrayWithTransform(values as Any?, transform: transform)
  437. }
  438. #else
  439. let transformed2DArray = original2DArray.flatMap { values in
  440. fromJSONArrayWithTransform(values as Any?, transform: transform)
  441. }
  442. #endif
  443. FromJSON.basicType(&left, object: transformed2DArray)
  444. default:
  445. break
  446. }
  447. }
  448. public func >>> <Transform: TransformType>(left: [[Transform.Object]], right: (Map, Transform)) {
  449. let (map, transform) = right
  450. if map.mappingType == .toJSON{
  451. #if swift(>=4.1)
  452. let transformed2DArray = left.compactMap { values in
  453. toJSONArrayWithTransform(values, transform: transform)
  454. }
  455. #else
  456. let transformed2DArray = left.flatMap { values in
  457. toJSONArrayWithTransform(values, transform: transform)
  458. }
  459. #endif
  460. ToJSON.basicType(transformed2DArray, map: map)
  461. }
  462. }
  463. /// Optional array of array of objects with transform
  464. public func <- <Transform: TransformType>(left: inout [[Transform.Object]]?, right: (Map, Transform)) {
  465. let (map, transform) = right
  466. switch map.mappingType {
  467. case .toJSON:
  468. left >>> right
  469. case .fromJSON where map.isKeyPresent:
  470. guard let original2DArray = map.currentValue as? [[Any]] else { break }
  471. #if swift(>=4.1)
  472. let transformed2DArray = original2DArray.compactMap { values in
  473. fromJSONArrayWithTransform(values as Any?, transform: transform)
  474. }
  475. #else
  476. let transformed2DArray = original2DArray.flatMap { values in
  477. fromJSONArrayWithTransform(values as Any?, transform: transform)
  478. }
  479. #endif
  480. FromJSON.optionalBasicType(&left, object: transformed2DArray)
  481. default:
  482. break
  483. }
  484. }
  485. public func >>> <Transform: TransformType>(left: [[Transform.Object]]?, right: (Map, Transform)) {
  486. let (map, transform) = right
  487. if map.mappingType == .toJSON {
  488. #if swift(>=4.1)
  489. let transformed2DArray = left?.compactMap { values in
  490. toJSONArrayWithTransform(values, transform: transform)
  491. }
  492. #else
  493. let transformed2DArray = left?.flatMap { values in
  494. toJSONArrayWithTransform(values, transform: transform)
  495. }
  496. #endif
  497. ToJSON.optionalBasicType(transformed2DArray, map: map)
  498. }
  499. }
  500. // Code targeting the Swift 4.1 compiler and below.
  501. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  502. /// Implicitly unwrapped Optional array of array of objects with transform
  503. public func <- <Transform: TransformType>(left: inout [[Transform.Object]]!, right: (Map, Transform)) {
  504. let (map, transform) = right
  505. switch map.mappingType {
  506. case .toJSON:
  507. left >>> right
  508. case .fromJSON where map.isKeyPresent:
  509. guard let original2DArray = map.currentValue as? [[Any]] else { break }
  510. #if swift(>=4.1)
  511. let transformed2DArray = original2DArray.compactMap { values in
  512. fromJSONArrayWithTransform(values as Any?, transform: transform)
  513. }
  514. #else
  515. let transformed2DArray = original2DArray.flatMap { values in
  516. fromJSONArrayWithTransform(values as Any?, transform: transform)
  517. }
  518. #endif
  519. FromJSON.optionalBasicType(&left, object: transformed2DArray)
  520. default:
  521. break
  522. }
  523. }
  524. #endif
  525. // MARK:- Set of Mappable objects with a transform - Set<T: BaseMappable>
  526. /// Set of Mappable objects with transform
  527. public func <- <Transform: TransformType>(left: inout Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  528. let (map, transform) = right
  529. switch map.mappingType {
  530. case .fromJSON where map.isKeyPresent:
  531. if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
  532. FromJSON.basicType(&left, object: Set(transformedValues))
  533. }
  534. case .toJSON:
  535. left >>> right
  536. default: ()
  537. }
  538. }
  539. public func >>> <Transform: TransformType>(left: Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
  540. let (map, transform) = right
  541. if map.mappingType == .toJSON {
  542. let transformedValues = toJSONArrayWithTransform(Array(left), transform: transform)
  543. ToJSON.optionalBasicType(transformedValues, map: map)
  544. }
  545. }
  546. /// Optional Set of Mappable objects with transform
  547. public func <- <Transform: TransformType>(left: inout Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  548. let (map, transform) = right
  549. switch map.mappingType {
  550. case .fromJSON where map.isKeyPresent:
  551. if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
  552. FromJSON.basicType(&left, object: Set(transformedValues))
  553. }
  554. case .toJSON:
  555. left >>> right
  556. default: ()
  557. }
  558. }
  559. public func >>> <Transform: TransformType>(left: Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
  560. let (map, transform) = right
  561. if map.mappingType == .toJSON {
  562. if let values = left {
  563. let transformedValues = toJSONArrayWithTransform(Array(values), transform: transform)
  564. ToJSON.optionalBasicType(transformedValues, map: map)
  565. }
  566. }
  567. }
  568. // Code targeting the Swift 4.1 compiler and below.
  569. #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
  570. /// Implicitly unwrapped Optional set of Mappable objects with transform
  571. public func <- <Transform: TransformType>(left: inout Set<Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
  572. let (map, transform) = right
  573. switch map.mappingType {
  574. case .fromJSON where map.isKeyPresent:
  575. if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
  576. FromJSON.basicType(&left, object: Set(transformedValues))
  577. }
  578. case .toJSON:
  579. left >>> right
  580. default: ()
  581. }
  582. }
  583. #endif
  584. private func fromJSONArrayWithTransform<Transform: TransformType>(_ input: Any?, transform: Transform) -> [Transform.Object]? {
  585. if let values = input as? [Any] {
  586. #if swift(>=4.1)
  587. return values.compactMap { value in
  588. return transform.transformFromJSON(value)
  589. }
  590. #else
  591. return values.flatMap { value in
  592. return transform.transformFromJSON(value)
  593. }
  594. #endif
  595. } else {
  596. return nil
  597. }
  598. }
  599. private func fromJSONDictionaryWithTransform<Transform: TransformType>(_ input: Any?, transform: Transform) -> [String: Transform.Object]? {
  600. if let values = input as? [String: Any] {
  601. return values.filterMap { value in
  602. return transform.transformFromJSON(value)
  603. }
  604. } else {
  605. return nil
  606. }
  607. }
  608. private func toJSONArrayWithTransform<Transform: TransformType>(_ input: [Transform.Object]?, transform: Transform) -> [Transform.JSON]? {
  609. #if swift(>=4.1)
  610. return input?.compactMap { value in
  611. return transform.transformToJSON(value)
  612. }
  613. #else
  614. return input?.flatMap { value in
  615. return transform.transformToJSON(value)
  616. }
  617. #endif
  618. }
  619. private func toJSONDictionaryWithTransform<Transform: TransformType>(_ input: [String: Transform.Object]?, transform: Transform) -> [String: Transform.JSON]? {
  620. return input?.filterMap { value in
  621. return transform.transformToJSON(value)
  622. }
  623. }