@capacitor-plus/ios 8.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Capacitor/Capacitor/AppUUID.swift +51 -0
- package/Capacitor/Capacitor/Array+Capacitor.swift +31 -0
- package/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift +32 -0
- package/Capacitor/Capacitor/CAPBridge.swift +25 -0
- package/Capacitor/Capacitor/CAPBridgeDelegate.swift +6 -0
- package/Capacitor/Capacitor/CAPBridgeProtocol.swift +148 -0
- package/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.h +6 -0
- package/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.m +5 -0
- package/Capacitor/Capacitor/CAPBridgeViewController.swift +384 -0
- package/Capacitor/Capacitor/CAPBridgedJSTypes.h +18 -0
- package/Capacitor/Capacitor/CAPBridgedJSTypes.m +43 -0
- package/Capacitor/Capacitor/CAPBridgedPlugin+getMethod.swift +13 -0
- package/Capacitor/Capacitor/CAPBridgedPlugin.h +41 -0
- package/Capacitor/Capacitor/CAPFile.swift +14 -0
- package/Capacitor/Capacitor/CAPInstanceConfiguration.h +38 -0
- package/Capacitor/Capacitor/CAPInstanceConfiguration.m +93 -0
- package/Capacitor/Capacitor/CAPInstanceConfiguration.swift +78 -0
- package/Capacitor/Capacitor/CAPInstanceDescriptor.h +167 -0
- package/Capacitor/Capacitor/CAPInstanceDescriptor.m +56 -0
- package/Capacitor/Capacitor/CAPInstanceDescriptor.swift +198 -0
- package/Capacitor/Capacitor/CAPInstancePlugin.swift +10 -0
- package/Capacitor/Capacitor/CAPLog.swift +11 -0
- package/Capacitor/Capacitor/CAPNotifications.swift +69 -0
- package/Capacitor/Capacitor/CAPPlugin+LoadInstance.swift +20 -0
- package/Capacitor/Capacitor/CAPPlugin.h +60 -0
- package/Capacitor/Capacitor/CAPPlugin.m +180 -0
- package/Capacitor/Capacitor/CAPPluginCall.h +25 -0
- package/Capacitor/Capacitor/CAPPluginCall.m +36 -0
- package/Capacitor/Capacitor/CAPPluginCall.swift +97 -0
- package/Capacitor/Capacitor/CAPPluginMethod.h +36 -0
- package/Capacitor/Capacitor/CAPPluginMethod.m +44 -0
- package/Capacitor/Capacitor/CAPPluginMethod.swift +17 -0
- package/Capacitor/Capacitor/Capacitor.h +15 -0
- package/Capacitor/Capacitor/Capacitor.modulemap +8 -0
- package/Capacitor/Capacitor/CapacitorBridge.swift +768 -0
- package/Capacitor/Capacitor/CapacitorExtension.swift +24 -0
- package/Capacitor/Capacitor/Codable/JSValueDecoder.swift +479 -0
- package/Capacitor/Capacitor/Codable/JSValueEncoder.swift +671 -0
- package/Capacitor/Capacitor/Data+Capacitor.swift +22 -0
- package/Capacitor/Capacitor/DocLinks.swift +8 -0
- package/Capacitor/Capacitor/Info.plist +24 -0
- package/Capacitor/Capacitor/JS.swift +122 -0
- package/Capacitor/Capacitor/JSExport.swift +218 -0
- package/Capacitor/Capacitor/JSTypes.swift +254 -0
- package/Capacitor/Capacitor/KeyPath.swift +60 -0
- package/Capacitor/Capacitor/KeyValueStore.swift +303 -0
- package/Capacitor/Capacitor/NotificationHandlerProtocol.swift +6 -0
- package/Capacitor/Capacitor/NotificationRouter.swift +60 -0
- package/Capacitor/Capacitor/PluginCallResult.swift +106 -0
- package/Capacitor/Capacitor/PluginConfig.swift +56 -0
- package/Capacitor/Capacitor/Plugins/CapacitorCookieManager.swift +141 -0
- package/Capacitor/Capacitor/Plugins/CapacitorCookies.swift +57 -0
- package/Capacitor/Capacitor/Plugins/CapacitorHttp.swift +57 -0
- package/Capacitor/Capacitor/Plugins/CapacitorUrlRequest.swift +225 -0
- package/Capacitor/Capacitor/Plugins/Console.swift +16 -0
- package/Capacitor/Capacitor/Plugins/HttpRequestHandler.swift +236 -0
- package/Capacitor/Capacitor/Plugins/SystemBars.swift +133 -0
- package/Capacitor/Capacitor/Plugins/WebView.swift +44 -0
- package/Capacitor/Capacitor/PrivacyInfo.xcprivacy +14 -0
- package/Capacitor/Capacitor/Router.swift +29 -0
- package/Capacitor/Capacitor/TmpViewController.swift +8 -0
- package/Capacitor/Capacitor/UIColor.swift +55 -0
- package/Capacitor/Capacitor/UIStatusBarManager+CAPHandleTapAction.m +37 -0
- package/Capacitor/Capacitor/WKWebView+Capacitor.m +15 -0
- package/Capacitor/Capacitor/WKWebView+Capacitor.swift +80 -0
- package/Capacitor/Capacitor/WebViewAssetHandler.swift +550 -0
- package/Capacitor/Capacitor/WebViewDelegationHandler.swift +361 -0
- package/Capacitor/Capacitor/assets/native-bridge.js +1029 -0
- package/Capacitor.podspec +23 -0
- package/CapacitorCordova/CapacitorCordova/CapacitorCordova.h +25 -0
- package/CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap +6 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.h +8 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.m +5 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDV.h +28 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailability.h +109 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailabilityDeprecated.h +21 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegate.h +49 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.h +39 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.m +149 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.h +31 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.m +81 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.h +52 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.m +116 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.h +39 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.m +38 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.h +76 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.m +136 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.h +25 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.m +77 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h +82 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m +216 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVScreenOrientationDelegate.h +33 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.h +27 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.m +74 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h +30 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.m +37 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.h +34 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.m +55 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.h +35 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.m +63 -0
- package/CapacitorCordova/CapacitorCordova/Info.plist +26 -0
- package/CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy +14 -0
- package/CapacitorCordova.podspec +26 -0
- package/LICENSE +21 -0
- package/package.json +33 -0
- package/scripts/pods_helpers.rb +12 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public protocol CapacitorExtension {
|
|
4
|
+
associatedtype CapacitorType
|
|
5
|
+
var capacitor: CapacitorType { get }
|
|
6
|
+
static var capacitor: CapacitorType.Type { get }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public extension CapacitorExtension {
|
|
10
|
+
var capacitor: CapacitorExtensionTypeWrapper<Self> {
|
|
11
|
+
return CapacitorExtensionTypeWrapper(self)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static var capacitor: CapacitorExtensionTypeWrapper<Self>.Type {
|
|
15
|
+
return CapacitorExtensionTypeWrapper.self
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public struct CapacitorExtensionTypeWrapper<T> {
|
|
20
|
+
var baseType: T
|
|
21
|
+
init(_ baseType: T) {
|
|
22
|
+
self.baseType = baseType
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
//
|
|
2
|
+
// JSValueDecoder.swift
|
|
3
|
+
// Capacitor
|
|
4
|
+
//
|
|
5
|
+
// Created by Steven Sherry on 12/8/23.
|
|
6
|
+
// Copyright © 2023 Drifty Co. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import Combine
|
|
11
|
+
|
|
12
|
+
/// A decoder that can decode ``JSValue`` objects into `Decodable` types.
|
|
13
|
+
public final class JSValueDecoder: TopLevelDecoder {
|
|
14
|
+
/// The strategies available for formatting dates when decoding from a ``JSValue``
|
|
15
|
+
public typealias DateDecodingStrategy = JSONDecoder.DateDecodingStrategy
|
|
16
|
+
/// The strategies available for decoding raw data.
|
|
17
|
+
public typealias DataDecodingStrategy = JSONDecoder.DataDecodingStrategy
|
|
18
|
+
|
|
19
|
+
/// The strategies availble for decoding NaN, Infinity, and -Infinity
|
|
20
|
+
public enum NonConformingFloatDecodingStrategy {
|
|
21
|
+
/// Decodes directly into the floating point type as .infinity, -.infinity, or .nan
|
|
22
|
+
case deferred
|
|
23
|
+
/// Throw an error when a non-conforming float is encountered
|
|
24
|
+
case `throw`
|
|
25
|
+
/// Converts from the provided strings into .infinity, -.infinity, or .nan
|
|
26
|
+
case convertFromString(positiveInfinity: String, negativeInfinity: String, nan: String)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fileprivate struct Options {
|
|
30
|
+
var dataStrategy: DataDecodingStrategy
|
|
31
|
+
var dateStrategy: DateDecodingStrategy
|
|
32
|
+
var nonConformingStrategy: NonConformingFloatDecodingStrategy
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private var options: Options
|
|
36
|
+
|
|
37
|
+
/// Creates a new JSValueDecoder with the provided decoding and formatting strategies
|
|
38
|
+
/// - Parameters:
|
|
39
|
+
/// - dateDecodingStrategy: Defaults to `DateDecodingStrategy.deferredToDate`
|
|
40
|
+
/// - dataDecodingStrategy: Defaults to `DataDecodingStrategy.deferredToData`
|
|
41
|
+
/// - nonConformingFloatDecodingStrategy: Defaults to ``NonConformingFloatDecodingStrategy/deferred``
|
|
42
|
+
public init(
|
|
43
|
+
dateDecodingStrategy: DateDecodingStrategy = .deferredToDate,
|
|
44
|
+
dataDecodingStrategy: DataDecodingStrategy = .deferredToData,
|
|
45
|
+
nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy = .deferred
|
|
46
|
+
) {
|
|
47
|
+
self.options = .init(dataStrategy: dataDecodingStrategy, dateStrategy: dateDecodingStrategy, nonConformingStrategy: nonConformingFloatDecodingStrategy)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fileprivate init(options: Options) {
|
|
51
|
+
self.options = options
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// The strategy to use when decoding dates from a ``JSValue``
|
|
55
|
+
public var dateDecodingStrategy: DateDecodingStrategy {
|
|
56
|
+
get { options.dateStrategy }
|
|
57
|
+
set { options.dateStrategy = newValue }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// The strategy to use when decoding raw data from a ``JSValue``
|
|
61
|
+
public var dataDecodingStrategy: DataDecodingStrategy {
|
|
62
|
+
get { options.dataStrategy }
|
|
63
|
+
set { options.dataStrategy = newValue }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// The strategy used by a decoder when it encounters exceptional floating-point values
|
|
67
|
+
public var nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy {
|
|
68
|
+
get { options.nonConformingStrategy }
|
|
69
|
+
set { options.nonConformingStrategy = newValue }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// Decodes a ``JSValue`` into the provided `Decodable` type
|
|
73
|
+
/// - Parameters:
|
|
74
|
+
/// - type: The type of the value to decode from the provided ``JSValue`` object
|
|
75
|
+
/// - data: The ``JSValue`` to decode
|
|
76
|
+
/// - Returns: A value of the specified type.
|
|
77
|
+
///
|
|
78
|
+
/// An error will be thrown from this method for two possible reasons:
|
|
79
|
+
/// 1. A type mismatch was found.
|
|
80
|
+
/// 2. A key was not found in the `data` field that is required in the `type` provided.
|
|
81
|
+
public func decode<T>(_ type: T.Type, from data: JSValue) throws -> T where T: Decodable {
|
|
82
|
+
let decoder = _JSValueDecoder(data: data, options: options)
|
|
83
|
+
return try decoder.decodeData(as: T.self)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
typealias CodingUserInfo = [CodingUserInfoKey: Any]
|
|
88
|
+
private typealias Options = JSValueDecoder.Options
|
|
89
|
+
|
|
90
|
+
private final class _JSValueDecoder {
|
|
91
|
+
var codingPath: [CodingKey] = []
|
|
92
|
+
var userInfo: CodingUserInfo = [:]
|
|
93
|
+
var options: Options
|
|
94
|
+
fileprivate var data: JSValue
|
|
95
|
+
|
|
96
|
+
init(data: JSValue, options: Options) {
|
|
97
|
+
self.data = data
|
|
98
|
+
self.options = options
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
extension _JSValueDecoder: Decoder {
|
|
103
|
+
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
|
|
104
|
+
guard let data = data as? JSObject else {
|
|
105
|
+
throw DecodingError.typeMismatch(JSObject.self, on: data, codingPath: codingPath)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return KeyedDecodingContainer(
|
|
109
|
+
KeyedContainer(
|
|
110
|
+
data: data,
|
|
111
|
+
codingPath: codingPath,
|
|
112
|
+
userInfo: userInfo,
|
|
113
|
+
options: options
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func unkeyedContainer() throws -> UnkeyedDecodingContainer {
|
|
119
|
+
guard let data = data as? JSArray else {
|
|
120
|
+
throw DecodingError.typeMismatch(JSArray.self, on: data, codingPath: codingPath)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return UnkeyedContainer(data: data, codingPath: codingPath, userInfo: userInfo, options: options)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
func singleValueContainer() throws -> SingleValueDecodingContainer {
|
|
127
|
+
SingleValueContainer(data: data, codingPath: codingPath, userInfo: userInfo, options: options)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// force casting is fine becasue we've already determined that T is the type in the case
|
|
131
|
+
// the swift standard library also force casts in their similar functions
|
|
132
|
+
// https://github.com/swiftlang/swift-foundation/blob/da80d51fa3e77f3e7ed57c4300a870689e755713/Sources/FoundationEssentials/JSON/JSONEncoder.swift#L1140
|
|
133
|
+
// swiftlint:disable force_cast
|
|
134
|
+
fileprivate func decodeData<T>(as type: T.Type) throws -> T where T: Decodable {
|
|
135
|
+
switch type {
|
|
136
|
+
case is Date.Type:
|
|
137
|
+
return try decodeDate() as! T
|
|
138
|
+
case is URL.Type:
|
|
139
|
+
return try decodeUrl() as! T
|
|
140
|
+
case is Data.Type:
|
|
141
|
+
return try decodeData() as! T
|
|
142
|
+
default:
|
|
143
|
+
return try T(from: self)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// swiftlint:enable force_cast
|
|
147
|
+
|
|
148
|
+
private func decodeDate() throws -> Date {
|
|
149
|
+
switch options.dateStrategy {
|
|
150
|
+
case .deferredToDate:
|
|
151
|
+
return try Date(from: self)
|
|
152
|
+
case .secondsSince1970:
|
|
153
|
+
guard let value = data as? NSNumber else { throw DecodingError.dataCorrupted(data, target: Double.self, codingPath: codingPath) }
|
|
154
|
+
return Date(timeIntervalSince1970: value.doubleValue)
|
|
155
|
+
case .millisecondsSince1970:
|
|
156
|
+
guard let value = data as? NSNumber else { throw DecodingError.dataCorrupted(data, target: Double.self, codingPath: codingPath) }
|
|
157
|
+
return Date(timeIntervalSince1970: value.doubleValue / Double(MSEC_PER_SEC))
|
|
158
|
+
case .iso8601:
|
|
159
|
+
guard let value = data as? String else { throw DecodingError.dataCorrupted(data, target: String.self, codingPath: codingPath) }
|
|
160
|
+
let formatter = ISO8601DateFormatter()
|
|
161
|
+
guard let date = formatter.date(from: value) else { throw DecodingError.dataCorrupted(value, target: Date.self, codingPath: codingPath) }
|
|
162
|
+
return date
|
|
163
|
+
case .formatted(let formatter):
|
|
164
|
+
guard let value = data as? String else { throw DecodingError.dataCorrupted(data, target: String.self, codingPath: codingPath) }
|
|
165
|
+
guard let date = formatter.date(from: value) else { throw DecodingError.dataCorrupted(value, target: Date.self, codingPath: codingPath) }
|
|
166
|
+
return date
|
|
167
|
+
case .custom(let decode):
|
|
168
|
+
return try decode(self)
|
|
169
|
+
@unknown default:
|
|
170
|
+
return try Date(from: self)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private func decodeUrl() throws -> URL {
|
|
175
|
+
guard let str = data as? String,
|
|
176
|
+
let url = URL(string: str)
|
|
177
|
+
else { throw DecodingError.dataCorrupted(data, target: URL.self, codingPath: codingPath) }
|
|
178
|
+
|
|
179
|
+
return url
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private func decodeData() throws -> Data {
|
|
183
|
+
switch options.dataStrategy {
|
|
184
|
+
case .deferredToData:
|
|
185
|
+
return try Data(from: self)
|
|
186
|
+
case .base64:
|
|
187
|
+
guard let value = data as? String else { throw DecodingError.dataCorrupted(data, target: String.self, codingPath: codingPath) }
|
|
188
|
+
guard let data = Data(base64Encoded: value) else { throw DecodingError.dataCorrupted(value, target: Data.self, codingPath: codingPath) }
|
|
189
|
+
return data
|
|
190
|
+
case .custom(let decode):
|
|
191
|
+
return try decode(self)
|
|
192
|
+
@unknown default:
|
|
193
|
+
return try Data(from: self)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private final class KeyedContainer<Key> where Key: CodingKey {
|
|
199
|
+
var data: JSObject
|
|
200
|
+
var codingPath: [CodingKey]
|
|
201
|
+
var userInfo: CodingUserInfo
|
|
202
|
+
var allKeys: [Key]
|
|
203
|
+
var options: Options
|
|
204
|
+
|
|
205
|
+
init(data: JSObject, codingPath: [CodingKey], userInfo: CodingUserInfo, options: Options) {
|
|
206
|
+
self.data = data
|
|
207
|
+
self.codingPath = codingPath
|
|
208
|
+
self.userInfo = userInfo
|
|
209
|
+
self.allKeys = data.keys.compactMap(Key.init(stringValue:))
|
|
210
|
+
self.options = options
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
extension KeyedContainer: KeyedDecodingContainerProtocol {
|
|
215
|
+
func contains(_ key: Key) -> Bool {
|
|
216
|
+
allKeys.contains { $0.stringValue == key.stringValue }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
func decodeNil(forKey key: Key) throws -> Bool {
|
|
220
|
+
data[key.stringValue] == nil || data[key.stringValue] is NSNull
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable {
|
|
224
|
+
guard let rawValue = data[key.stringValue] else {
|
|
225
|
+
throw DecodingError.keyNotFound(key, on: data, codingPath: codingPath)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var newPath = codingPath
|
|
229
|
+
newPath.append(key)
|
|
230
|
+
let decoder = _JSValueDecoder(data: rawValue, options: options)
|
|
231
|
+
return try decoder.decodeData(as: T.self)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
|
|
235
|
+
var newPath = codingPath
|
|
236
|
+
newPath.append(key)
|
|
237
|
+
guard let data = data[key.stringValue] as? JSArray else {
|
|
238
|
+
throw DecodingError.typeMismatch(
|
|
239
|
+
JSArray.self,
|
|
240
|
+
on: data[key.stringValue] ?? "null value",
|
|
241
|
+
codingPath: newPath
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return UnkeyedContainer(data: data, codingPath: newPath, userInfo: userInfo, options: options)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
|
|
249
|
+
var newPath = codingPath
|
|
250
|
+
newPath.append(key)
|
|
251
|
+
guard let data = data[key.stringValue] as? JSObject else {
|
|
252
|
+
throw DecodingError.typeMismatch(
|
|
253
|
+
JSObject.self,
|
|
254
|
+
on: data[key.stringValue] ?? "null value",
|
|
255
|
+
codingPath: newPath
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return KeyedDecodingContainer(KeyedContainer<NestedKey>(data: data, codingPath: newPath, userInfo: userInfo, options: options))
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
enum SuperKey: String, CodingKey { case `super` }
|
|
263
|
+
|
|
264
|
+
func superDecoder() throws -> Decoder {
|
|
265
|
+
var newPath = codingPath
|
|
266
|
+
newPath.append(SuperKey.super)
|
|
267
|
+
guard let data = data[SuperKey.super.stringValue] else {
|
|
268
|
+
throw DecodingError.keyNotFound(SuperKey.super, on: data, codingPath: newPath)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return _JSValueDecoder(data: data, options: options)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
func superDecoder(forKey key: Key) throws -> Decoder {
|
|
275
|
+
var newPath = codingPath
|
|
276
|
+
newPath.append(key)
|
|
277
|
+
guard let data = data[key.stringValue] else {
|
|
278
|
+
throw DecodingError.keyNotFound(key, on: data, codingPath: newPath)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return _JSValueDecoder(data: data, options: options)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private final class UnkeyedContainer {
|
|
286
|
+
var data: JSArray
|
|
287
|
+
var codingPath: [CodingKey]
|
|
288
|
+
var userInfo: CodingUserInfo
|
|
289
|
+
private(set) var currentIndex = 0
|
|
290
|
+
var options: Options
|
|
291
|
+
|
|
292
|
+
init(data: JSArray, codingPath: [CodingKey], userInfo: CodingUserInfo, options: Options) {
|
|
293
|
+
self.data = data
|
|
294
|
+
self.codingPath = codingPath
|
|
295
|
+
self.userInfo = userInfo
|
|
296
|
+
self.options = options
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
extension UnkeyedContainer: UnkeyedDecodingContainer {
|
|
301
|
+
var count: Int? {
|
|
302
|
+
data.count
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
var isAtEnd: Bool {
|
|
306
|
+
currentIndex == data.endIndex
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
func decodeNil() throws -> Bool {
|
|
310
|
+
defer { currentIndex += 1 }
|
|
311
|
+
return data[currentIndex] is NSNull
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
|
|
315
|
+
defer { currentIndex += 1 }
|
|
316
|
+
let decoder = _JSValueDecoder(data: data[currentIndex], options: options)
|
|
317
|
+
return try decoder.decodeData(as: T.self)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
|
|
321
|
+
defer { currentIndex += 1 }
|
|
322
|
+
guard let data = data[currentIndex] as? JSArray else {
|
|
323
|
+
throw DecodingError.typeMismatch(JSArray.self, on: data[currentIndex], codingPath: codingPath)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return UnkeyedContainer(data: data, codingPath: codingPath, userInfo: userInfo, options: options)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
|
|
330
|
+
defer { currentIndex += 1 }
|
|
331
|
+
guard let data = data[currentIndex] as? JSObject else {
|
|
332
|
+
throw DecodingError.typeMismatch(JSObject.self, on: data[currentIndex], codingPath: codingPath)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return KeyedDecodingContainer(KeyedContainer(data: data, codingPath: codingPath, userInfo: userInfo, options: options))
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
func superDecoder() throws -> Decoder {
|
|
339
|
+
defer { currentIndex += 1 }
|
|
340
|
+
let data = data[currentIndex]
|
|
341
|
+
return _JSValueDecoder(data: data, options: options)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
private final class SingleValueContainer {
|
|
346
|
+
var data: JSValue
|
|
347
|
+
var codingPath: [CodingKey]
|
|
348
|
+
var userInfo: CodingUserInfo
|
|
349
|
+
var options: Options
|
|
350
|
+
|
|
351
|
+
init(data: JSValue, codingPath: [CodingKey], userInfo: CodingUserInfo, options: Options) {
|
|
352
|
+
self.data = data
|
|
353
|
+
self.codingPath = codingPath
|
|
354
|
+
self.userInfo = userInfo
|
|
355
|
+
self.options = options
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
extension SingleValueContainer: SingleValueDecodingContainer {
|
|
360
|
+
func decodeNil() -> Bool {
|
|
361
|
+
return data is NSNull
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
private func cast<T>(to type: T.Type) throws -> T {
|
|
365
|
+
guard let data = data as? T else {
|
|
366
|
+
throw DecodingError.typeMismatch(type, on: data, codingPath: codingPath)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return data
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
private func castFloat<N>(to type: N.Type) throws -> N where N: FloatingPoint {
|
|
373
|
+
if let data = data as? String,
|
|
374
|
+
case let .convertFromString(positiveInfinity: pos, negativeInfinity: neg, nan: nan) = options.nonConformingStrategy {
|
|
375
|
+
switch data {
|
|
376
|
+
case pos:
|
|
377
|
+
return N.infinity
|
|
378
|
+
case neg:
|
|
379
|
+
return -N.infinity
|
|
380
|
+
case nan:
|
|
381
|
+
return N.nan
|
|
382
|
+
default:
|
|
383
|
+
throw DecodingError.typeMismatch(type, on: data, codingPath: codingPath)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
let data = try cast(to: N.self)
|
|
388
|
+
if !data.isFinite, case .throw = options.nonConformingStrategy {
|
|
389
|
+
throw DecodingError.dataCorrupted(.init(codingPath: codingPath, debugDescription: "\(data) is a non-conforming floating point number"))
|
|
390
|
+
}
|
|
391
|
+
return data
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
func decode(_ type: Bool.Type) throws -> Bool {
|
|
395
|
+
try cast(to: type)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
func decode(_ type: String.Type) throws -> String {
|
|
399
|
+
try cast(to: type)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
func decode(_ type: Double.Type) throws -> Double {
|
|
403
|
+
try castFloat(to: type)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
func decode(_ type: Float.Type) throws -> Float {
|
|
407
|
+
try castFloat(to: type)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
func decode(_ type: Int.Type) throws -> Int {
|
|
411
|
+
try cast(to: type)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
func decode(_ type: Int8.Type) throws -> Int8 {
|
|
415
|
+
try cast(to: type)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
func decode(_ type: Int16.Type) throws -> Int16 {
|
|
419
|
+
try cast(to: type)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
func decode(_ type: Int32.Type) throws -> Int32 {
|
|
423
|
+
try cast(to: type)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
func decode(_ type: Int64.Type) throws -> Int64 {
|
|
427
|
+
try cast(to: type)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
func decode(_ type: UInt.Type) throws -> UInt {
|
|
431
|
+
try cast(to: type)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
func decode(_ type: UInt8.Type) throws -> UInt8 {
|
|
435
|
+
try cast(to: type)
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
func decode(_ type: UInt16.Type) throws -> UInt16 {
|
|
439
|
+
try cast(to: type)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
func decode(_ type: UInt32.Type) throws -> UInt32 {
|
|
443
|
+
try cast(to: type)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
func decode(_ type: UInt64.Type) throws -> UInt64 {
|
|
447
|
+
try cast(to: type)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
|
|
451
|
+
let decoder = _JSValueDecoder(data: data, options: options)
|
|
452
|
+
return try decoder.decodeData(as: T.self)
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
extension DecodingError {
|
|
457
|
+
static func typeMismatch(_ type: Any.Type, on data: any JSValue, codingPath: [CodingKey]) -> DecodingError {
|
|
458
|
+
return .typeMismatch(
|
|
459
|
+
type,
|
|
460
|
+
.init(
|
|
461
|
+
codingPath: codingPath,
|
|
462
|
+
debugDescription: "\(data) was unable to be cast to \(type)."
|
|
463
|
+
)
|
|
464
|
+
)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
static func keyNotFound(_ key: any CodingKey, on data: any JSValue, codingPath: [CodingKey]) -> DecodingError {
|
|
468
|
+
return .keyNotFound(
|
|
469
|
+
key,
|
|
470
|
+
.init(
|
|
471
|
+
codingPath: codingPath,
|
|
472
|
+
debugDescription: "Key \(key.stringValue) not found in \(data)")
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
static func dataCorrupted<T>(_ value: any JSValue, target type: T.Type, codingPath: [CodingKey]) -> DecodingError where T: Decodable {
|
|
477
|
+
return .dataCorrupted(.init(codingPath: codingPath, debugDescription: "\(value) was not in the format expected for \(T.self)"))
|
|
478
|
+
}
|
|
479
|
+
}
|