How to use _PlistEncoder class

Best Swift-snapshot-testing code snippet using ._PlistEncoder

Run Swift-snapshot-testing automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

PlistEncoder.swift

Source: PlistEncoder.swift Github

copy
1//===----------------------------------------------------------------------===//
2//
3// This source file is part of the Swift.org open source project
4//
5// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6// Licensed under Apache License v2.0 with Runtime Library Exception
7//
8// See https://swift.org/LICENSE.txt for license information
9// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// Plist Encoder
15//===----------------------------------------------------------------------===//
16
17/// `PropertyListEncoder` facilitates the encoding of `Encodable` values into property lists.
18open class PropertyListEncoder {
19
20    // MARK: - Options
21
22    /// The output format to write the property list data in. Defaults to `.binary`.
23    open var outputFormat: PropertyListSerialization.PropertyListFormat = .binary
24
25    /// Contextual user-provided information for use during encoding.
26    open var userInfo: [CodingUserInfoKey : Any] = [:]
27
28    /// Options set on the top-level encoder to pass down the encoding hierarchy.
29    fileprivate struct _Options {
30        let outputFormat: PropertyListSerialization.PropertyListFormat
31        let userInfo: [CodingUserInfoKey : Any]
32    }
33
34    /// The options set on the top-level encoder.
35    fileprivate var options: _Options {
36        return _Options(outputFormat: outputFormat, userInfo: userInfo)
37    }
38
39    // MARK: - Constructing a Property List Encoder
40
41    /// Initializes `self` with default strategies.
42    public init() {}
43
44    // MARK: - Encoding Values
45
46    /// Encodes the given top-level value and returns its property list representation.
47    ///
48    /// - parameter value: The value to encode.
49    /// - returns: A new `Data` value containing the encoded property list data.
50    /// - throws: `EncodingError.invalidValue` if a non-conforming floating-point value is encountered during encoding, and the encoding strategy is `.throw`.
51    /// - throws: An error if any value throws an error during encoding.
52    open func encode<Value : Encodable>(_ value: Value) throws -> Data {
53      let topLevel = try encodeToTopLevelContainer(value)
54      if topLevel is NSNumber {
55          throw EncodingError.invalidValue(value,
56                                           EncodingError.Context(codingPath: [],
57                                                                 debugDescription: "Top-level \(Value.self) encoded as number property list fragment."))
58      } else if topLevel is NSString {
59          throw EncodingError.invalidValue(value,
60                                           EncodingError.Context(codingPath: [],
61                                                                 debugDescription: "Top-level \(Value.self) encoded as string property list fragment."))
62      } else if topLevel is NSDate {
63          throw EncodingError.invalidValue(value,
64                                           EncodingError.Context(codingPath: [],
65                                                                 debugDescription: "Top-level \(Value.self) encoded as date property list fragment."))
66      }
67      
68      do {
69          return try PropertyListSerialization.data(fromPropertyList: topLevel, format: self.outputFormat, options: 0)
70      } catch {
71          throw EncodingError.invalidValue(value, 
72                                           EncodingError.Context(codingPath: [], debugDescription: "Unable to encode the given top-level value as a property list", underlyingError: error))
73      }
74    }
75
76    /// Encodes the given top-level value and returns its plist-type representation.
77    ///
78    /// - parameter value: The value to encode.
79    /// - returns: A new top-level array or dictionary representing the value.
80    /// - throws: `EncodingError.invalidValue` if a non-conforming floating-point value is encountered during encoding, and the encoding strategy is `.throw`.
81    /// - throws: An error if any value throws an error during encoding.
82    internal func encodeToTopLevelContainer<Value : Encodable>(_ value: Value) throws -> Any {
83        let encoder = _PlistEncoder(options: self.options)
84        guard let topLevel = try encoder.box_(value) else {
85            throw EncodingError.invalidValue(value,
86                                             EncodingError.Context(codingPath: [],
87                                                                   debugDescription: "Top-level \(Value.self) did not encode any values."))
88        }
89
90        return topLevel
91    }
92}
93
94// MARK: - _PlistEncoder
95
96fileprivate class _PlistEncoder : Encoder {
97    // MARK: Properties
98
99    /// The encoder's storage.
100    fileprivate var storage: _PlistEncodingStorage
101
102    /// Options set on the top-level encoder.
103    fileprivate let options: PropertyListEncoder._Options
104
105    /// The path to the current point in encoding.
106    fileprivate(set) public var codingPath: [CodingKey]
107
108    /// Contextual user-provided information for use during encoding.
109    public var userInfo: [CodingUserInfoKey : Any] {
110        return self.options.userInfo
111    }
112
113    // MARK: - Initialization
114
115    /// Initializes `self` with the given top-level encoder options.
116    fileprivate init(options: PropertyListEncoder._Options, codingPath: [CodingKey] = []) {
117        self.options = options
118        self.storage = _PlistEncodingStorage()
119        self.codingPath = codingPath
120    }
121
122    /// Returns whether a new element can be encoded at this coding path.
123    ///
124    /// `true` if an element has not yet been encoded at this coding path; `false` otherwise.
125    fileprivate var canEncodeNewValue: Bool {
126        // Every time a new value gets encoded, the key it's encoded for is pushed onto the coding path (even if it's a nil key from an unkeyed container).
127        // At the same time, every time a container is requested, a new value gets pushed onto the storage stack.
128        // If there are more values on the storage stack than on the coding path, it means the value is requesting more than one container, which violates the precondition.
129        //
130        // This means that anytime something that can request a new container goes onto the stack, we MUST push a key onto the coding path.
131        // Things which will not request containers do not need to have the coding path extended for them (but it doesn't matter if it is, because they will not reach here).
132        return self.storage.count == self.codingPath.count
133    }
134
135    // MARK: - Encoder Methods
136    public func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
137        // If an existing keyed container was already requested, return that one.
138        let topContainer: NSMutableDictionary
139        if self.canEncodeNewValue {
140            // We haven't yet pushed a container at this level; do so here.
141            topContainer = self.storage.pushKeyedContainer()
142        } else {
143            guard let container = self.storage.containers.last as? NSMutableDictionary else {
144                preconditionFailure("Attempt to push new keyed encoding container when already previously encoded at this path.")
145            }
146
147            topContainer = container
148        }
149
150        let container = _PlistKeyedEncodingContainer<Key>(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
151        return KeyedEncodingContainer(container)
152    }
153
154    public func unkeyedContainer() -> UnkeyedEncodingContainer {
155        // If an existing unkeyed container was already requested, return that one.
156        let topContainer: NSMutableArray
157        if self.canEncodeNewValue {
158            // We haven't yet pushed a container at this level; do so here.
159            topContainer = self.storage.pushUnkeyedContainer()
160        } else {
161            guard let container = self.storage.containers.last as? NSMutableArray else {
162                preconditionFailure("Attempt to push new unkeyed encoding container when already previously encoded at this path.")
163            }
164
165            topContainer = container
166        }
167
168        return _PlistUnkeyedEncodingContainer(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
169    }
170
171    public func singleValueContainer() -> SingleValueEncodingContainer {
172        return self
173    }
174}
175
176// MARK: - Encoding Storage and Containers
177
178fileprivate struct _PlistEncodingStorage {
179    // MARK: Properties
180
181    /// The container stack.
182    /// Elements may be any one of the plist types (NSNumber, NSString, NSDate, NSArray, NSDictionary).
183    private(set) fileprivate var containers: [NSObject] = []
184
185    // MARK: - Initialization
186
187    /// Initializes `self` with no containers.
188    fileprivate init() {}
189
190    // MARK: - Modifying the Stack
191
192    fileprivate var count: Int {
193        return self.containers.count
194    }
195
196    fileprivate mutating func pushKeyedContainer() -> NSMutableDictionary {
197        let dictionary = NSMutableDictionary()
198        self.containers.append(dictionary)
199        return dictionary
200    }
201
202    fileprivate mutating func pushUnkeyedContainer() -> NSMutableArray {
203        let array = NSMutableArray()
204        self.containers.append(array)
205        return array
206    }
207
208    fileprivate mutating func push(container: NSObject) {
209        self.containers.append(container)
210    }
211
212    fileprivate mutating func popContainer() -> NSObject {
213        precondition(!self.containers.isEmpty, "Empty container stack.")
214        return self.containers.popLast()!
215    }
216}
217
218// MARK: - Encoding Containers
219
220fileprivate struct _PlistKeyedEncodingContainer<K : CodingKey> : KeyedEncodingContainerProtocol {
221    typealias Key = K
222
223    // MARK: Properties
224
225    /// A reference to the encoder we're writing to.
226    private let encoder: _PlistEncoder
227
228    /// A reference to the container we're writing to.
229    private let container: NSMutableDictionary
230
231    /// The path of coding keys taken to get to this point in encoding.
232    private(set) public var codingPath: [CodingKey]
233
234    // MARK: - Initialization
235
236    /// Initializes `self` with the given references.
237    fileprivate init(referencing encoder: _PlistEncoder, codingPath: [CodingKey], wrapping container: NSMutableDictionary) {
238        self.encoder = encoder
239        self.codingPath = codingPath
240        self.container = container
241    }
242
243    // MARK: - KeyedEncodingContainerProtocol Methods
244
245    public mutating func encodeNil(forKey key: Key)               throws { self.container[key.stringValue] = _plistNullNSString }
246    public mutating func encode(_ value: Bool, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
247    public mutating func encode(_ value: Int, forKey key: Key)    throws { self.container[key.stringValue] = self.encoder.box(value) }
248    public mutating func encode(_ value: Int8, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
249    public mutating func encode(_ value: Int16, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
250    public mutating func encode(_ value: Int32, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
251    public mutating func encode(_ value: Int64, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
252    public mutating func encode(_ value: UInt, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
253    public mutating func encode(_ value: UInt8, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
254    public mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
255    public mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
256    public mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
257    public mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
258    public mutating func encode(_ value: Float, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
259    public mutating func encode(_ value: Double, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
260
261    public mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
262        self.encoder.codingPath.append(key)
263        defer { self.encoder.codingPath.removeLast() }
264        self.container[key.stringValue] = try self.encoder.box(value)
265    }
266
267    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
268        let dictionary = NSMutableDictionary()
269        self.container[key.stringValue] = dictionary
270
271        self.codingPath.append(key)
272        defer { self.codingPath.removeLast() }
273
274        let container = _PlistKeyedEncodingContainer<NestedKey>(referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary)
275        return KeyedEncodingContainer(container)
276    }
277
278    public mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
279        let array = NSMutableArray()
280        self.container[key.stringValue] = array
281
282        self.codingPath.append(key)
283        defer { self.codingPath.removeLast() }
284        return _PlistUnkeyedEncodingContainer(referencing: self.encoder, codingPath: self.codingPath, wrapping: array)
285    }
286
287    public mutating func superEncoder() -> Encoder {
288        return _PlistReferencingEncoder(referencing: self.encoder, at: _PlistKey.super, wrapping: self.container)
289    }
290
291    public mutating func superEncoder(forKey key: Key) -> Encoder {
292        return _PlistReferencingEncoder(referencing: self.encoder, at: key, wrapping: self.container)
293    }
294}
295
296fileprivate struct _PlistUnkeyedEncodingContainer : UnkeyedEncodingContainer {
297    // MARK: Properties
298
299    /// A reference to the encoder we're writing to.
300    private let encoder: _PlistEncoder
301
302    /// A reference to the container we're writing to.
303    private let container: NSMutableArray
304
305    /// The path of coding keys taken to get to this point in encoding.
306    private(set) public var codingPath: [CodingKey]
307
308    /// The number of elements encoded into the container.
309    public var count: Int {
310        return self.container.count
311    }
312
313    // MARK: - Initialization
314
315    /// Initializes `self` with the given references.
316    fileprivate init(referencing encoder: _PlistEncoder, codingPath: [CodingKey], wrapping container: NSMutableArray) {
317        self.encoder = encoder
318        self.codingPath = codingPath
319        self.container = container
320    }
321
322    // MARK: - UnkeyedEncodingContainer Methods
323
324    public mutating func encodeNil()             throws { self.container.add(_plistNullNSString) }
325    public mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
326    public mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
327    public mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
328    public mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
329    public mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
330    public mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
331    public mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
332    public mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
333    public mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
334    public mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
335    public mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
336    public mutating func encode(_ value: Float)  throws { self.container.add(self.encoder.box(value)) }
337    public mutating func encode(_ value: Double) throws { self.container.add(self.encoder.box(value)) }
338    public mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
339
340    public mutating func encode<T : Encodable>(_ value: T) throws {
341        self.encoder.codingPath.append(_PlistKey(index: self.count))
342        defer { self.encoder.codingPath.removeLast() }
343        self.container.add(try self.encoder.box(value))
344    }
345
346    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
347        self.codingPath.append(_PlistKey(index: self.count))
348        defer { self.codingPath.removeLast() }
349
350        let dictionary = NSMutableDictionary()
351        self.container.add(dictionary)
352
353        let container = _PlistKeyedEncodingContainer<NestedKey>(referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary)
354        return KeyedEncodingContainer(container)
355    }
356
357    public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
358        self.codingPath.append(_PlistKey(index: self.count))
359        defer { self.codingPath.removeLast() }
360
361        let array = NSMutableArray()
362        self.container.add(array)
363        return _PlistUnkeyedEncodingContainer(referencing: self.encoder, codingPath: self.codingPath, wrapping: array)
364    }
365
366    public mutating func superEncoder() -> Encoder {
367        return _PlistReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container)
368    }
369}
370
371extension _PlistEncoder : SingleValueEncodingContainer {
372    // MARK: - SingleValueEncodingContainer Methods
373
374    private func assertCanEncodeNewValue() {
375        precondition(self.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
376    }
377
378    public func encodeNil() throws {
379        assertCanEncodeNewValue()
380        self.storage.push(container: _plistNullNSString)
381    }
382
383    public func encode(_ value: Bool) throws {
384        assertCanEncodeNewValue()
385        self.storage.push(container: self.box(value))
386    }
387
388    public func encode(_ value: Int) throws {
389        assertCanEncodeNewValue()
390        self.storage.push(container: self.box(value))
391    }
392
393    public func encode(_ value: Int8) throws {
394        assertCanEncodeNewValue()
395        self.storage.push(container: self.box(value))
396    }
397
398    public func encode(_ value: Int16) throws {
399        assertCanEncodeNewValue()
400        self.storage.push(container: self.box(value))
401    }
402
403    public func encode(_ value: Int32) throws {
404        assertCanEncodeNewValue()
405        self.storage.push(container: self.box(value))
406    }
407
408    public func encode(_ value: Int64) throws {
409        assertCanEncodeNewValue()
410        self.storage.push(container: self.box(value))
411    }
412
413    public func encode(_ value: UInt) throws {
414        assertCanEncodeNewValue()
415        self.storage.push(container: self.box(value))
416    }
417
418    public func encode(_ value: UInt8) throws {
419        assertCanEncodeNewValue()
420        self.storage.push(container: self.box(value))
421    }
422
423    public func encode(_ value: UInt16) throws {
424        assertCanEncodeNewValue()
425        self.storage.push(container: self.box(value))
426    }
427
428    public func encode(_ value: UInt32) throws {
429        assertCanEncodeNewValue()
430        self.storage.push(container: self.box(value))
431    }
432
433    public func encode(_ value: UInt64) throws {
434        assertCanEncodeNewValue()
435        self.storage.push(container: self.box(value))
436    }
437
438    public func encode(_ value: String) throws {
439        assertCanEncodeNewValue()
440        self.storage.push(container: self.box(value))
441    }
442
443    public func encode(_ value: Float) throws {
444        assertCanEncodeNewValue()
445        self.storage.push(container: self.box(value))
446    }
447
448    public func encode(_ value: Double) throws {
449        assertCanEncodeNewValue()
450        self.storage.push(container: self.box(value))
451    }
452
453    public func encode<T : Encodable>(_ value: T) throws {
454        assertCanEncodeNewValue()
455        try self.storage.push(container: self.box(value))
456    }
457}
458
459// MARK: - Concrete Value Representations
460
461extension _PlistEncoder {
462
463    /// Returns the given value boxed in a container appropriate for pushing onto the container stack.
464    fileprivate func box(_ value: Bool)   -> NSObject { return NSNumber(value: value) }
465    fileprivate func box(_ value: Int)    -> NSObject { return NSNumber(value: value) }
466    fileprivate func box(_ value: Int8)   -> NSObject { return NSNumber(value: value) }
467    fileprivate func box(_ value: Int16)  -> NSObject { return NSNumber(value: value) }
468    fileprivate func box(_ value: Int32)  -> NSObject { return NSNumber(value: value) }
469    fileprivate func box(_ value: Int64)  -> NSObject { return NSNumber(value: value) }
470    fileprivate func box(_ value: UInt)   -> NSObject { return NSNumber(value: value) }
471    fileprivate func box(_ value: UInt8)  -> NSObject { return NSNumber(value: value) }
472    fileprivate func box(_ value: UInt16) -> NSObject { return NSNumber(value: value) }
473    fileprivate func box(_ value: UInt32) -> NSObject { return NSNumber(value: value) }
474    fileprivate func box(_ value: UInt64) -> NSObject { return NSNumber(value: value) }
475    fileprivate func box(_ value: Float)  -> NSObject { return NSNumber(value: value) }
476    fileprivate func box(_ value: Double) -> NSObject { return NSNumber(value: value) }
477    fileprivate func box(_ value: String) -> NSObject { return NSString(string: value) }
478
479    fileprivate func box<T : Encodable>(_ value: T) throws -> NSObject {
480        return try self.box_(value) ?? NSDictionary()
481    }
482
483    fileprivate func box_<T : Encodable>(_ value: T) throws -> NSObject? {
484        if T.self == Date.self || T.self == NSDate.self {
485            // PropertyListSerialization handles NSDate directly.
486            return (value as! NSDate)
487        } else if T.self == Data.self || T.self == NSData.self {
488            // PropertyListSerialization handles NSData directly.
489            return (value as! NSData)
490        }
491
492        // The value should request a container from the _PlistEncoder.
493        let depth = self.storage.count
494        do {
495            try value.encode(to: self)
496        } catch let error {
497            // If the value pushed a container before throwing, pop it back off to restore state.
498            if self.storage.count > depth {
499                let _ = self.storage.popContainer()
500            }
501
502            throw error
503        }
504
505        // The top container should be a new container.
506        guard self.storage.count > depth else {
507            return nil
508        }
509
510        return self.storage.popContainer()
511    }
512}
513
514// MARK: - _PlistReferencingEncoder
515
516/// _PlistReferencingEncoder is a special subclass of _PlistEncoder which has its own storage, but references the contents of a different encoder.
517/// It's used in superEncoder(), which returns a new encoder for encoding a superclass -- the lifetime of the encoder should not escape the scope it's created in, but it doesn't necessarily know when it's done being used (to write to the original container).
518fileprivate class _PlistReferencingEncoder : _PlistEncoder {
519    // MARK: Reference types.
520
521    /// The type of container we're referencing.
522    private enum Reference {
523        /// Referencing a specific index in an array container.
524        case array(NSMutableArray, Int)
525
526        /// Referencing a specific key in a dictionary container.
527        case dictionary(NSMutableDictionary, String)
528    }
529
530    // MARK: - Properties
531
532    /// The encoder we're referencing.
533    private let encoder: _PlistEncoder
534
535    /// The container reference itself.
536    private let reference: Reference
537
538    // MARK: - Initialization
539
540    /// Initializes `self` by referencing the given array container in the given encoder.
541    fileprivate init(referencing encoder: _PlistEncoder, at index: Int, wrapping array: NSMutableArray) {
542        self.encoder = encoder
543        self.reference = .array(array, index)
544        super.init(options: encoder.options, codingPath: encoder.codingPath)
545
546        self.codingPath.append(_PlistKey(index: index))
547    }
548
549    /// Initializes `self` by referencing the given dictionary container in the given encoder.
550    fileprivate init(referencing encoder: _PlistEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
551        self.encoder = encoder
552        self.reference = .dictionary(dictionary, key.stringValue)
553        super.init(options: encoder.options, codingPath: encoder.codingPath)
554
555        self.codingPath.append(key)
556    }
557
558    // MARK: - Coding Path Operations
559
560    fileprivate override var canEncodeNewValue: Bool {
561        // With a regular encoder, the storage and coding path grow together.
562        // A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
563        // We have to take this into account.
564        return self.storage.count == self.codingPath.count - self.encoder.codingPath.count - 1
565    }
566
567    // MARK: - Deinitialization
568
569    // Finalizes `self` by writing the contents of our storage to the referenced encoder's storage.
570    deinit {
571        let value: Any
572        switch self.storage.count {
573        case 0: value = NSDictionary()
574        case 1: value = self.storage.popContainer()
575        default: fatalError("Referencing encoder deallocated with multiple containers on stack.")
576        }
577
578        switch self.reference {
579        case .array(let array, let index):
580            array.insert(value, at: index)
581
582        case .dictionary(let dictionary, let key):
583            dictionary[NSString(string: key)] = value
584        }
585    }
586}
587
588//===----------------------------------------------------------------------===//
589// Plist Decoder
590//===----------------------------------------------------------------------===//
591
592/// `PropertyListDecoder` facilitates the decoding of property list values into semantic `Decodable` types.
593open class PropertyListDecoder {
594    // MARK: Options
595
596    /// Contextual user-provided information for use during decoding.
597    open var userInfo: [CodingUserInfoKey : Any] = [:]
598
599    /// Options set on the top-level encoder to pass down the decoding hierarchy.
600    fileprivate struct _Options {
601        let userInfo: [CodingUserInfoKey : Any]
602    }
603
604    /// The options set on the top-level decoder.
605    fileprivate var options: _Options {
606        return _Options(userInfo: userInfo)
607    }
608
609    // MARK: - Constructing a Property List Decoder
610
611    /// Initializes `self` with default strategies.
612    public init() {}
613
614    // MARK: - Decoding Values
615
616    /// Decodes a top-level value of the given type from the given property list representation.
617    ///
618    /// - parameter type: The type of the value to decode.
619    /// - parameter data: The data to decode from.
620    /// - returns: A value of the requested type.
621    /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not a valid property list.
622    /// - throws: An error if any value throws an error during decoding.
623    open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
624        var format: PropertyListSerialization.PropertyListFormat = .binary
625        return try decode(type, from: data, format: &format)
626    }
627
628    /// Decodes a top-level value of the given type from the given property list representation.
629    ///
630    /// - parameter type: The type of the value to decode.
631    /// - parameter data: The data to decode from.
632    /// - parameter format: The parsed property list format.
633    /// - returns: A value of the requested type along with the detected format of the property list.
634    /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not a valid property list.
635    /// - throws: An error if any value throws an error during decoding.
636    open func decode<T : Decodable>(_ type: T.Type, from data: Data, format: inout PropertyListSerialization.PropertyListFormat) throws -> T {
637        let topLevel: Any
638        do {
639            topLevel = try PropertyListSerialization.propertyList(from: data, options: [], format: &format)
640        } catch {
641            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not a valid property list.", underlyingError: error))
642        }
643
644        return try decode(type, fromTopLevel: topLevel)
645    }
646
647    /// Decodes a top-level value of the given type from the given property list container (top-level array or dictionary).
648    ///
649    /// - parameter type: The type of the value to decode.
650    /// - parameter container: The top-level plist container.
651    /// - returns: A value of the requested type.
652    /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not a valid property list.
653    /// - throws: An error if any value throws an error during decoding.
654    internal func decode<T : Decodable>(_ type: T.Type, fromTopLevel container: Any) throws -> T {
655        let decoder = _PlistDecoder(referencing: container, options: self.options)
656        guard let value = try decoder.unbox(container, as: type) else {
657            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
658        }
659
660        return value
661    }
662}
663
664// MARK: - _PlistDecoder
665
666fileprivate class _PlistDecoder : Decoder {
667    // MARK: Properties
668
669    /// The decoder's storage.
670    fileprivate var storage: _PlistDecodingStorage
671
672    /// Options set on the top-level decoder.
673    fileprivate let options: PropertyListDecoder._Options
674
675    /// The path to the current point in encoding.
676    fileprivate(set) public var codingPath: [CodingKey]
677
678    /// Contextual user-provided information for use during encoding.
679    public var userInfo: [CodingUserInfoKey : Any] {
680        return self.options.userInfo
681    }
682
683    // MARK: - Initialization
684
685    /// Initializes `self` with the given top-level container and options.
686    fileprivate init(referencing container: Any, at codingPath: [CodingKey] = [], options: PropertyListDecoder._Options) {
687        self.storage = _PlistDecodingStorage()
688        self.storage.push(container: container)
689        self.codingPath = codingPath
690        self.options = options
691    }
692
693    // MARK: - Decoder Methods
694
695    public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
696        guard !(self.storage.topContainer is NSNull) else {
697            throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
698                                              DecodingError.Context(codingPath: self.codingPath,
699                                                      debugDescription: "Cannot get keyed decoding container -- found null value instead."))
700        }
701
702        guard let topContainer = self.storage.topContainer as? [String : Any] else {
703            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [String : Any].self, reality: self.storage.topContainer)
704        }
705
706        let container = _PlistKeyedDecodingContainer<Key>(referencing: self, wrapping: topContainer)
707        return KeyedDecodingContainer(container)
708    }
709
710    public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
711        guard !(self.storage.topContainer is NSNull) else {
712            throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
713                                              DecodingError.Context(codingPath: self.codingPath,
714                                                      debugDescription: "Cannot get unkeyed decoding container -- found null value instead."))
715        }
716
717        guard let topContainer = self.storage.topContainer as? [Any] else {
718            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [Any].self, reality: self.storage.topContainer)
719        }
720
721        return _PlistUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
722    }
723
724    public func singleValueContainer() throws -> SingleValueDecodingContainer {
725        return self
726    }
727}
728
729// MARK: - Decoding Storage
730
731fileprivate struct _PlistDecodingStorage {
732    // MARK: Properties
733
734    /// The container stack.
735    /// Elements may be any one of the plist types (NSNumber, Date, String, Array, [String : Any]).
736    private(set) fileprivate var containers: [Any] = []
737
738    // MARK: - Initialization
739
740    /// Initializes `self` with no containers.
741    fileprivate init() {}
742
743    // MARK: - Modifying the Stack
744
745    fileprivate var count: Int {
746        return self.containers.count
747    }
748
749    fileprivate var topContainer: Any {
750        precondition(!self.containers.isEmpty, "Empty container stack.")
751        return self.containers.last!
752    }
753
754    fileprivate mutating func push(container: Any) {
755        self.containers.append(container)
756    }
757
758    fileprivate mutating func popContainer() {
759        precondition(!self.containers.isEmpty, "Empty container stack.")
760        self.containers.removeLast()
761    }
762}
763
764// MARK: Decoding Containers
765
766fileprivate struct _PlistKeyedDecodingContainer<K : CodingKey> : KeyedDecodingContainerProtocol {
767    typealias Key = K
768
769    // MARK: Properties
770
771    /// A reference to the decoder we're reading from.
772    private let decoder: _PlistDecoder
773
774    /// A reference to the container we're reading from.
775    private let container: [String : Any]
776
777    /// The path of coding keys taken to get to this point in decoding.
778    private(set) public var codingPath: [CodingKey]
779
780    // MARK: - Initialization
781
782    /// Initializes `self` by referencing the given decoder and container.
783    fileprivate init(referencing decoder: _PlistDecoder, wrapping container: [String : Any]) {
784        self.decoder = decoder
785        self.container = container
786        self.codingPath = decoder.codingPath
787    }
788
789    // MARK: - KeyedDecodingContainerProtocol Methods
790
791    public var allKeys: [Key] {
792        return self.container.keys.compactMap { Key(stringValue: $0) }
793    }
794
795    public func contains(_ key: Key) -> Bool {
796        return self.container[key.stringValue] != nil
797    }
798
799    public func decodeNil(forKey key: Key) throws -> Bool {
800        guard let entry = self.container[key.stringValue] else {
801            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
802        }
803
804        guard let value = entry as? String else {
805            return false
806        }
807
808        return value == _plistNull
809    }
810
811    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
812        guard let entry = self.container[key.stringValue] else {
813            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
814        }
815
816        self.decoder.codingPath.append(key)
817        defer { self.decoder.codingPath.removeLast() }
818
819        guard let value = try self.decoder.unbox(entry, as: Bool.self) else {
820            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
821        }
822
823        return value
824    }
825
826    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
827        guard let entry = self.container[key.stringValue] else {
828            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
829        }
830
831        self.decoder.codingPath.append(key)
832        defer { self.decoder.codingPath.removeLast() }
833
834        guard let value = try self.decoder.unbox(entry, as: Int.self) else {
835            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
836        }
837
838        return value
839    }
840
841    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
842        guard let entry = self.container[key.stringValue] else {
843            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
844        }
845
846        self.decoder.codingPath.append(key)
847        defer { self.decoder.codingPath.removeLast() }
848
849        guard let value = try self.decoder.unbox(entry, as: Int8.self) else {
850            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
851        }
852
853        return value
854    }
855
856    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
857        guard let entry = self.container[key.stringValue] else {
858            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
859        }
860
861        self.decoder.codingPath.append(key)
862        defer { self.decoder.codingPath.removeLast() }
863
864        guard let value = try self.decoder.unbox(entry, as: Int16.self) else {
865            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
866        }
867
868        return value
869    }
870
871    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
872        guard let entry = self.container[key.stringValue] else {
873            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
874        }
875
876        self.decoder.codingPath.append(key)
877        defer { self.decoder.codingPath.removeLast() }
878
879        guard let value = try self.decoder.unbox(entry, as: Int32.self) else {
880            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
881        }
882
883        return value
884    }
885
886    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
887        guard let entry = self.container[key.stringValue] else {
888            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
889        }
890
891        self.decoder.codingPath.append(key)
892        defer { self.decoder.codingPath.removeLast() }
893
894        guard let value = try self.decoder.unbox(entry, as: Int64.self) else {
895            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
896        }
897
898        return value
899    }
900
901    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
902        guard let entry = self.container[key.stringValue] else {
903            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
904        }
905
906        self.decoder.codingPath.append(key)
907        defer { self.decoder.codingPath.removeLast() }
908
909        guard let value = try self.decoder.unbox(entry, as: UInt.self) else {
910            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
911        }
912
913        return value
914    }
915
916    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
917        guard let entry = self.container[key.stringValue] else {
918            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
919        }
920
921        self.decoder.codingPath.append(key)
922        defer { self.decoder.codingPath.removeLast() }
923
924        guard let value = try self.decoder.unbox(entry, as: UInt8.self) else {
925            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
926        }
927
928        return value
929    }
930
931    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
932        guard let entry = self.container[key.stringValue] else {
933            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
934        }
935
936        self.decoder.codingPath.append(key)
937        defer { self.decoder.codingPath.removeLast() }
938
939        guard let value = try self.decoder.unbox(entry, as: UInt16.self) else {
940            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
941        }
942
943        return value
944    }
945
946    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
947        guard let entry = self.container[key.stringValue] else {
948            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
949        }
950
951        self.decoder.codingPath.append(key)
952        defer { self.decoder.codingPath.removeLast() }
953
954        guard let value = try self.decoder.unbox(entry, as: UInt32.self) else {
955            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
956        }
957
958        return value
959    }
960
961    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
962        guard let entry = self.container[key.stringValue] else {
963            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
964        }
965
966        self.decoder.codingPath.append(key)
967        defer { self.decoder.codingPath.removeLast() }
968
969        guard let value = try self.decoder.unbox(entry, as: UInt64.self) else {
970            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
971        }
972
973        return value
974    }
975
976    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
977        guard let entry = self.container[key.stringValue] else {
978            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
979        }
980
981        self.decoder.codingPath.append(key)
982        defer { self.decoder.codingPath.removeLast() }
983        guard let value = try self.decoder.unbox(entry, as: Float.self) else {
984            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
985        }
986
987        return value
988    }
989
990    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
991        guard let entry = self.container[key.stringValue] else {
992            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
993        }
994
995        self.decoder.codingPath.append(key)
996        defer { self.decoder.codingPath.removeLast() }
997
998        guard let value = try self.decoder.unbox(entry, as: Double.self) else {
999            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
1000        }
1001
1002        return value
1003    }
1004
1005    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
1006        guard let entry = self.container[key.stringValue] else {
1007            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
1008        }
1009
1010        self.decoder.codingPath.append(key)
1011        defer { self.decoder.codingPath.removeLast() }
1012
1013        guard let value = try self.decoder.unbox(entry, as: String.self) else {
1014            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
1015        }
1016
1017        return value
1018    }
1019
1020    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
1021        guard let entry = self.container[key.stringValue] else {
1022            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
1023        }
1024
1025        self.decoder.codingPath.append(key)
1026        defer { self.decoder.codingPath.removeLast() }
1027
1028        guard let value = try self.decoder.unbox(entry, as: type) else {
1029            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
1030        }
1031
1032        return value
1033    }
1034
1035    public func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
1036        self.decoder.codingPath.append(key)
1037        defer { self.decoder.codingPath.removeLast() }
1038
1039        guard let value = self.container[key.stringValue] else {
1040            throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
1041                                              DecodingError.Context(codingPath: self.codingPath,
1042                                                      debugDescription: "Cannot get nested keyed container -- no value found for key \"\(key.stringValue)\""))
1043        }
1044
1045        guard let dictionary = value as? [String : Any] else {
1046            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [String : Any].self, reality: value)
1047        }
1048
1049        let container = _PlistKeyedDecodingContainer<NestedKey>(referencing: self.decoder, wrapping: dictionary)
1050        return KeyedDecodingContainer(container)
1051    }
1052
1053    public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
1054        self.decoder.codingPath.append(key)
1055        defer { self.decoder.codingPath.removeLast() }
1056
1057        guard let value = self.container[key.stringValue] else {
1058            throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
1059                                              DecodingError.Context(codingPath: self.codingPath,
1060                                                      debugDescription: "Cannot get nested unkeyed container -- no value found for key \"\(key.stringValue)\""))
1061        }
1062
1063        guard let array = value as? [Any] else {
1064            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [Any].self, reality: value)
1065        }
1066
1067        return _PlistUnkeyedDecodingContainer(referencing: self.decoder, wrapping: array)
1068    }
1069
1070    private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
1071        self.decoder.codingPath.append(key)
1072        defer { self.decoder.codingPath.removeLast() }
1073
1074        let value: Any = self.container[key.stringValue] ?? NSNull()
1075        return _PlistDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
1076    }
1077
1078    public func superDecoder() throws -> Decoder {
1079        return try _superDecoder(forKey: _PlistKey.super)
1080    }
1081
1082    public func superDecoder(forKey key: Key) throws -> Decoder {
1083        return try _superDecoder(forKey: key)
1084    }
1085}
1086
1087fileprivate struct _PlistUnkeyedDecodingContainer : UnkeyedDecodingContainer {
1088    // MARK: Properties
1089
1090    /// A reference to the decoder we're reading from.
1091    private let decoder: _PlistDecoder
1092
1093    /// A reference to the container we're reading from.
1094    private let container: [Any]
1095
1096    /// The path of coding keys taken to get to this point in decoding.
1097    private(set) public var codingPath: [CodingKey]
1098
1099    /// The index of the element we're about to decode.
1100    private(set) public var currentIndex: Int
1101
1102    // MARK: - Initialization
1103
1104    /// Initializes `self` by referencing the given decoder and container.
1105    fileprivate init(referencing decoder: _PlistDecoder, wrapping container: [Any]) {
1106        self.decoder = decoder
1107        self.container = container
1108        self.codingPath = decoder.codingPath
1109        self.currentIndex = 0
1110    }
1111
1112    // MARK: - UnkeyedDecodingContainer Methods
1113
1114    public var count: Int? {
1115        return self.container.count
1116    }
1117
1118    public var isAtEnd: Bool {
1119        return self.currentIndex >= self.count!
1120    }
1121
1122    public mutating func decodeNil() throws -> Bool {
1123        guard !self.isAtEnd else {
1124            throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1125        }
1126
1127        if self.container[self.currentIndex] is NSNull {
1128            self.currentIndex += 1
1129            return true
1130        } else {
1131            return false
1132        }
1133    }
1134
1135    public mutating func decode(_ type: Bool.Type) throws -> Bool {
1136        guard !self.isAtEnd else {
1137            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1138        }
1139
1140        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1141        defer { self.decoder.codingPath.removeLast() }
1142
1143        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self) else {
1144            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1145        }
1146
1147        self.currentIndex += 1
1148        return decoded
1149    }
1150
1151    public mutating func decode(_ type: Int.Type) throws -> Int {
1152        guard !self.isAtEnd else {
1153            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1154        }
1155
1156        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1157        defer { self.decoder.codingPath.removeLast() }
1158
1159        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self) else {
1160            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1161        }
1162
1163        self.currentIndex += 1
1164        return decoded
1165    }
1166
1167    public mutating func decode(_ type: Int8.Type) throws -> Int8 {
1168        guard !self.isAtEnd else {
1169            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1170        }
1171
1172        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1173        defer { self.decoder.codingPath.removeLast() }
1174
1175        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self) else {
1176            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1177        }
1178
1179        self.currentIndex += 1
1180        return decoded
1181    }
1182
1183    public mutating func decode(_ type: Int16.Type) throws -> Int16 {
1184        guard !self.isAtEnd else {
1185            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1186        }
1187
1188        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1189        defer { self.decoder.codingPath.removeLast() }
1190
1191        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self) else {
1192            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1193        }
1194
1195        self.currentIndex += 1
1196        return decoded
1197    }
1198
1199    public mutating func decode(_ type: Int32.Type) throws -> Int32 {
1200        guard !self.isAtEnd else {
1201            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1202        }
1203
1204        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1205        defer { self.decoder.codingPath.removeLast() }
1206
1207        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self) else {
1208            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1209        }
1210
1211        self.currentIndex += 1
1212        return decoded
1213    }
1214
1215    public mutating func decode(_ type: Int64.Type) throws -> Int64 {
1216        guard !self.isAtEnd else {
1217            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1218        }
1219
1220        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1221        defer { self.decoder.codingPath.removeLast() }
1222
1223        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self) else {
1224            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1225        }
1226
1227        self.currentIndex += 1
1228        return decoded
1229    }
1230
1231    public mutating func decode(_ type: UInt.Type) throws -> UInt {
1232        guard !self.isAtEnd else {
1233            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1234        }
1235
1236        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1237        defer { self.decoder.codingPath.removeLast() }
1238
1239        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self) else {
1240            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1241        }
1242
1243        self.currentIndex += 1
1244        return decoded
1245    }
1246
1247    public mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
1248        guard !self.isAtEnd else {
1249            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1250        }
1251
1252        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1253        defer { self.decoder.codingPath.removeLast() }
1254
1255        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self) else {
1256            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1257        }
1258
1259        self.currentIndex += 1
1260        return decoded
1261    }
1262
1263    public mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
1264        guard !self.isAtEnd else {
1265            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1266        }
1267
1268        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1269        defer { self.decoder.codingPath.removeLast() }
1270
1271        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self) else {
1272            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1273        }
1274
1275        self.currentIndex += 1
1276        return decoded
1277    }
1278
1279    public mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
1280        guard !self.isAtEnd else {
1281            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1282        }
1283
1284        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1285        defer { self.decoder.codingPath.removeLast() }
1286
1287        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self) else {
1288            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1289        }
1290
1291        self.currentIndex += 1
1292        return decoded
1293    }
1294
1295    public mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
1296        guard !self.isAtEnd else {
1297            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1298        }
1299
1300        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1301        defer { self.decoder.codingPath.removeLast() }
1302
1303        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self) else {
1304            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1305        }
1306
1307        self.currentIndex += 1
1308        return decoded
1309    }
1310
1311    public mutating func decode(_ type: Float.Type) throws -> Float {
1312        guard !self.isAtEnd else {
1313            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1314        }
1315
1316        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1317        defer { self.decoder.codingPath.removeLast() }
1318
1319        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self) else {
1320            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1321        }
1322
1323        self.currentIndex += 1
1324        return decoded
1325    }
1326
1327    public mutating func decode(_ type: Double.Type) throws -> Double {
1328        guard !self.isAtEnd else {
1329            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1330        }
1331
1332        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1333        defer { self.decoder.codingPath.removeLast() }
1334
1335        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self) else {
1336            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1337        }
1338
1339        self.currentIndex += 1
1340        return decoded
1341    }
1342
1343    public mutating func decode(_ type: String.Type) throws -> String {
1344        guard !self.isAtEnd else {
1345            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1346        }
1347
1348        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1349        defer { self.decoder.codingPath.removeLast() }
1350
1351        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self) else {
1352            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1353        }
1354
1355        self.currentIndex += 1
1356        return decoded
1357    }
1358
1359    public mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
1360        guard !self.isAtEnd else {
1361            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
1362        }
1363
1364        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1365        defer { self.decoder.codingPath.removeLast() }
1366
1367        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
1368            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
1369        }
1370
1371        self.currentIndex += 1
1372        return decoded
1373    }
1374
1375    public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
1376        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1377        defer { self.decoder.codingPath.removeLast() }
1378
1379        guard !self.isAtEnd else {
1380            throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
1381                                              DecodingError.Context(codingPath: self.codingPath,
1382                                                      debugDescription: "Cannot get nested keyed container -- unkeyed container is at end."))
1383        }
1384
1385        let value = self.container[self.currentIndex]
1386        guard !(value is NSNull) else {
1387            throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
1388                                              DecodingError.Context(codingPath: self.codingPath,
1389                                                      debugDescription: "Cannot get keyed decoding container -- found null value instead."))
1390        }
1391
1392        guard let dictionary = value as? [String : Any] else {
1393            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [String : Any].self, reality: value)
1394        }
1395
1396        self.currentIndex += 1
1397        let container = _PlistKeyedDecodingContainer<NestedKey>(referencing: self.decoder, wrapping: dictionary)
1398        return KeyedDecodingContainer(container)
1399    }
1400
1401    public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
1402        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1403        defer { self.decoder.codingPath.removeLast() }
1404
1405        guard !self.isAtEnd else {
1406            throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
1407                                              DecodingError.Context(codingPath: self.codingPath,
1408                                                      debugDescription: "Cannot get nested unkeyed container -- unkeyed container is at end."))
1409        }
1410
1411        let value = self.container[self.currentIndex]
1412        guard !(value is NSNull) else {
1413            throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
1414                                              DecodingError.Context(codingPath: self.codingPath,
1415                                                      debugDescription: "Cannot get keyed decoding container -- found null value instead."))
1416        }
1417
1418        guard let array = value as? [Any] else {
1419            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [Any].self, reality: value)
1420        }
1421
1422        self.currentIndex += 1
1423        return _PlistUnkeyedDecodingContainer(referencing: self.decoder, wrapping: array)
1424    }
1425
1426    public mutating func superDecoder() throws -> Decoder {
1427        self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
1428        defer { self.decoder.codingPath.removeLast() }
1429
1430        guard !self.isAtEnd else {
1431            throw DecodingError.valueNotFound(Decoder.self, DecodingError.Context(codingPath: self.codingPath,
1432                                                                    debugDescription: "Cannot get superDecoder() -- unkeyed container is at end."))
1433        }
1434
1435        let value = self.container[self.currentIndex]
1436        self.currentIndex += 1
1437        return _PlistDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
1438    }
1439}
1440
1441extension _PlistDecoder : SingleValueDecodingContainer {
1442    // MARK: SingleValueDecodingContainer Methods
1443
1444    private func expectNonNull<T>(_ type: T.Type) throws {
1445        guard !self.decodeNil() else {
1446            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
1447        }
1448    }
1449
1450    public func decodeNil() -> Bool {
1451        guard let string = self.storage.topContainer as? String else {
1452            return false
1453        }
1454
1455        return string == _plistNull
1456    }
1457
1458    public func decode(_ type: Bool.Type) throws -> Bool {
1459        try expectNonNull(Bool.self)
1460        return try self.unbox(self.storage.topContainer, as: Bool.self)!
1461    }
1462
1463    public func decode(_ type: Int.Type) throws -> Int {
1464        try expectNonNull(Int.self)
1465        return try self.unbox(self.storage.topContainer, as: Int.self)!
1466    }
1467
1468    public func decode(_ type: Int8.Type) throws -> Int8 {
1469        try expectNonNull(Int8.self)
1470        return try self.unbox(self.storage.topContainer, as: Int8.self)!
1471    }
1472
1473    public func decode(_ type: Int16.Type) throws -> Int16 {
1474        try expectNonNull(Int16.self)
1475        return try self.unbox(self.storage.topContainer, as: Int16.self)!
1476    }
1477
1478    public func decode(_ type: Int32.Type) throws -> Int32 {
1479        try expectNonNull(Int32.self)
1480        return try self.unbox(self.storage.topContainer, as: Int32.self)!
1481    }
1482
1483    public func decode(_ type: Int64.Type) throws -> Int64 {
1484        try expectNonNull(Int64.self)
1485        return try self.unbox(self.storage.topContainer, as: Int64.self)!
1486    }
1487
1488    public func decode(_ type: UInt.Type) throws -> UInt {
1489        try expectNonNull(UInt.self)
1490        return try self.unbox(self.storage.topContainer, as: UInt.self)!
1491    }
1492
1493    public func decode(_ type: UInt8.Type) throws -> UInt8 {
1494        try expectNonNull(UInt8.self)
1495        return try self.unbox(self.storage.topContainer, as: UInt8.self)!
1496    }
1497
1498    public func decode(_ type: UInt16.Type) throws -> UInt16 {
1499        try expectNonNull(UInt16.self)
1500        return try self.unbox(self.storage.topContainer, as: UInt16.self)!
1501    }
1502
1503    public func decode(_ type: UInt32.Type) throws -> UInt32 {
1504        try expectNonNull(UInt32.self)
1505        return try self.unbox(self.storage.topContainer, as: UInt32.self)!
1506    }
1507
1508    public func decode(_ type: UInt64.Type) throws -> UInt64 {
1509        try expectNonNull(UInt64.self)
1510        return try self.unbox(self.storage.topContainer, as: UInt64.self)!
1511    }
1512
1513    public func decode(_ type: Float.Type) throws -> Float {
1514        try expectNonNull(Float.self)
1515        return try self.unbox(self.storage.topContainer, as: Float.self)!
1516    }
1517
1518    public func decode(_ type: Double.Type) throws -> Double {
1519        try expectNonNull(Double.self)
1520        return try self.unbox(self.storage.topContainer, as: Double.self)!
1521    }
1522
1523    public func decode(_ type: String.Type) throws -> String {
1524        try expectNonNull(String.self)
1525        return try self.unbox(self.storage.topContainer, as: String.self)!
1526    }
1527
1528    public func decode<T : Decodable>(_ type: T.Type) throws -> T {
1529        try expectNonNull(type)
1530        return try self.unbox(self.storage.topContainer, as: type)!
1531    }
1532}
1533
1534// MARK: - Concrete Value Representations
1535
1536extension _PlistDecoder {
1537    /// Returns the given value unboxed from a container.
1538    fileprivate func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
1539        if let string = value as? String, string == _plistNull { return nil }
1540
1541        if let number = value as? NSNumber {
1542            // TODO: Add a flag to coerce non-boolean numbers into Bools?
1543            if number === kCFBooleanTrue as NSNumber {
1544                return true
1545            } else if number === kCFBooleanFalse as NSNumber {
1546                return false
1547            }
1548
1549        /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
1550        } else if let bool = value as? Bool {
1551            return bool
1552        */
1553
1554        }
1555
1556        throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1557    }
1558
1559    fileprivate func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
1560        if let string = value as? String, string == _plistNull { return nil }
1561
1562        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1563            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1564        }
1565
1566        let int = number.intValue
1567        guard NSNumber(value: int) == number else {
1568            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1569        }
1570
1571        return int
1572    }
1573
1574    fileprivate func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
1575        if let string = value as? String, string == _plistNull { return nil }
1576
1577        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1578            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1579        }
1580
1581        let int8 = number.int8Value
1582        guard NSNumber(value: int8) == number else {
1583            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1584        }
1585
1586        return int8
1587    }
1588
1589    fileprivate func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
1590        if let string = value as? String, string == _plistNull { return nil }
1591
1592        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1593            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1594        }
1595
1596        let int16 = number.int16Value
1597        guard NSNumber(value: int16) == number else {
1598            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1599        }
1600
1601        return int16
1602    }
1603
1604    fileprivate func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
1605        if let string = value as? String, string == _plistNull { return nil }
1606
1607        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1608            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1609        }
1610
1611        let int32 = number.int32Value
1612        guard NSNumber(value: int32) == number else {
1613            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1614        }
1615
1616        return int32
1617    }
1618
1619    fileprivate func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
1620        if let string = value as? String, string == _plistNull { return nil }
1621
1622        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1623            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1624        }
1625
1626        let int64 = number.int64Value
1627        guard NSNumber(value: int64) == number else {
1628            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1629        }
1630
1631        return int64
1632    }
1633
1634    fileprivate func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
1635        if let string = value as? String, string == _plistNull { return nil }
1636
1637        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1638            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1639        }
1640
1641        let uint = number.uintValue
1642        guard NSNumber(value: uint) == number else {
1643            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1644        }
1645
1646        return uint
1647    }
1648
1649    fileprivate func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
1650        if let string = value as? String, string == _plistNull { return nil }
1651
1652        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1653            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1654        }
1655
1656        let uint8 = number.uint8Value
1657        guard NSNumber(value: uint8) == number else {
1658            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1659        }
1660
1661        return uint8
1662    }
1663
1664    fileprivate func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
1665        if let string = value as? String, string == _plistNull { return nil }
1666
1667        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1668            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1669        }
1670
1671        let uint16 = number.uint16Value
1672        guard NSNumber(value: uint16) == number else {
1673            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1674        }
1675
1676        return uint16
1677    }
1678
1679    fileprivate func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
1680        if let string = value as? String, string == _plistNull { return nil }
1681
1682        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1683            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1684        }
1685
1686        let uint32 = number.uint32Value
1687        guard NSNumber(value: uint32) == number else {
1688            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1689        }
1690
1691        return uint32
1692    }
1693
1694    fileprivate func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
1695        if let string = value as? String, string == _plistNull { return nil }
1696
1697        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1698            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1699        }
1700
1701        let uint64 = number.uint64Value
1702        guard NSNumber(value: uint64) == number else {
1703            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1704        }
1705
1706        return uint64
1707    }
1708
1709    fileprivate func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
1710        if let string = value as? String, string == _plistNull { return nil }
1711
1712        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1713            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1714        }
1715
1716        let float = number.floatValue
1717        guard NSNumber(value: float) == number else {
1718            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1719        }
1720
1721        return float
1722    }
1723
1724    fileprivate func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
1725        if let string = value as? String, string == _plistNull { return nil }
1726
1727        guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
1728            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1729        }
1730
1731        let double = number.doubleValue
1732        guard NSNumber(value: double) == number else {
1733            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed property list number <\(number)> does not fit in \(type)."))
1734        }
1735
1736        return double
1737    }
1738
1739    fileprivate func unbox(_ value: Any, as type: String.Type) throws -> String? {
1740        guard let string = value as? String else {
1741            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1742        }
1743
1744        return string == _plistNull ? nil : string
1745    }
1746
1747    fileprivate func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
1748        if let string = value as? String, string == _plistNull { return nil }
1749
1750        guard let date = value as? Date else {
1751            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1752        }
1753
1754        return date
1755    }
1756
1757    fileprivate func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
1758        if let string = value as? String, string == _plistNull { return nil }
1759
1760        guard let data = value as? Data else {
1761            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
1762        }
1763
1764        return data
1765    }
1766
1767    fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
1768        if type == Date.self || type == NSDate.self {
1769            return try self.unbox(value, as: Date.self) as? T
1770        } else if type == Data.self || type == NSData.self {
1771            return try self.unbox(value, as: Data.self) as? T
1772        } else {
1773            self.storage.push(container: value)
1774            defer { self.storage.popContainer() }
1775            return try type.init(from: self)
1776        }
1777    }
1778}
1779
1780//===----------------------------------------------------------------------===//
1781// Shared Plist Null Representation
1782//===----------------------------------------------------------------------===//
1783
1784// Since plists do not support null values by default, we will encode them as "$null".
1785fileprivate let _plistNull = "$null"
1786fileprivate let _plistNullNSString = NSString(string: _plistNull)
1787
1788//===----------------------------------------------------------------------===//
1789// Shared Key Types
1790//===----------------------------------------------------------------------===//
1791
1792fileprivate struct _PlistKey : CodingKey {
1793    public var stringValue: String
1794    public var intValue: Int?
1795
1796    public init?(stringValue: String) {
1797        self.stringValue = stringValue
1798        self.intValue = nil
1799    }
1800
1801    public init?(intValue: Int) {
1802        self.stringValue = "\(intValue)"
1803        self.intValue = intValue
1804    }
1805
1806    fileprivate init(index: Int) {
1807        self.stringValue = "Index \(index)"
1808        self.intValue = index
1809    }
1810
1811    fileprivate static let `super` = _PlistKey(stringValue: "super")!
1812}
1813
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Most used methods in _PlistEncoder

Run Selenium Automation Tests on LambdaTest Cloud Grid

Trigger Selenium automation tests on a cloud-based Grid of 3000+ real browsers and operating systems.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)