forked from swiftlang/swift-corelibs-foundation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNSCoder.swift
763 lines (687 loc) · 32.2 KB
/
NSCoder.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
extension NSCoder {
/// Describes the action an `NSCoder` should take when it encounters decode
/// failures (e.g. corrupt data) for non-TopLevel decodes. Darwin platfrom
/// supports exceptions here, and there may be other approaches supported
/// in the future, so its included for completeness.
public enum DecodingFailurePolicy : Int {
case raiseException
case setErrorAndReturn
}
}
/// The `NSCoding` protocol declares the two methods that a class must implement
/// so that instances of that class can be encoded and decoded. This capability
/// provides the basis for archiving (where objects and other structures are
/// stored on disk) and distribution (where objects are copied to different
/// address spaces).
///
/// In keeping with object-oriented design principles, an object being encoded
/// or decoded is responsible for encoding and decoding its instance variables.
/// A coder instructs the object to do so by invoking `encode(with:)` or
/// `init(coder:)`. `encode(with:)` instructs the object to encode its instance
/// variables to the coder provided; this method can be invoked any number of
/// times. `init(coder:)` instructs the object to initialize itself from data
/// in the coder provided.
/// Any object class that should be codable must adopt the NSCoding protocol and
/// implement its methods.
public protocol NSCoding {
/// Encodes an instance of a conforming class using a given archiver.
///
/// - Parameter aCoder: An archiver object.
func encode(with aCoder: NSCoder)
/// Initializes an object from data in a given unarchiver.
///
/// - Parameter aDecoder: An unarchiver object.
init?(coder aDecoder: NSCoder)
}
/// Conforming to the `NSSecureCoding` protocol indicates that an object handles
/// encoding and decoding instances of itself in a manner that is robust against
/// object substitution attacks.
///
/// Historically, many classes decoded instances of themselves like this:
/// ```swift
/// if let object = decoder.decodeObject(forKey: "myKey") as? MyClass {
/// ...succeeds...
/// } else {
/// ...fail...
/// }
/// ```
/// This technique is potentially unsafe because by the time you can verify
/// the class type, the object has already been constructed, and if this is part
/// of a collection class, potentially inserted into an object graph.
///
/// In order to conform to `NSSecureCoding`:
/// - An object that does not override `init(coder:)` can conform to
/// `NSSecureCoding` without any changes (assuming that it is a subclass
/// of another class that conforms).
/// - An object that does override `init(coder:)` must decode any enclosed
/// objects using the `decodeObject(of:forKey:)` method. For example:
/// ```swift
/// let obj = decoder.decodeObject(of: MyClass.self, forKey: "myKey")
/// ```
/// In addition, the class must override its `NSSecureCoding` method to return
/// `true`.
public protocol NSSecureCoding : NSCoding {
static var supportsSecureCoding: Bool { get }
}
/// The `NSCoder` abstract class declares the interface used by concrete
/// subclasses to transfer objects and other values between memory and some
/// other format. This capability provides the basis for archiving (where
/// objects and data items are stored on disk) and distribution (where objects
/// and data items are copied between different processes or threads). The
/// concrete subclasses provided by Foundation for these purposes are
/// `NSKeyedArchiver` and `NSKeyedUnarchiver`. Concrete subclasses of `NSCoder`
/// are referred to in general as coder classes, and instances of these classes
/// as coder objects (or simply coders). A coder object that can only encode
/// values is referred to as an encoder object, and one that can only decode
/// values as a decoder object.
///
/// `NSCoder` operates on objects, scalars, C arrays, structures, and strings,
/// and on pointers to these types. It does not handle types whose
/// implementation varies across platforms, such as `UnsafeRawPointer`,
/// closures, and long chains of pointers. A coder object stores object type
/// information along with the data, so an object decoded from a stream of bytes
/// is normally of the same class as the object that was originally encoded into
/// the stream. An object can change its class when encoded, however; this is
/// described in Archives and Serializations Programming Guide.
open class NSCoder : NSObject {
internal var _pendingBuffers = Array<(UnsafeMutableRawPointer, Int)>()
deinit {
for buffer in _pendingBuffers {
// Cannot deinitialize a pointer to unknown type.
buffer.0.deallocate()
}
}
/// Must be overridden by subclasses to encode a single value residing at
/// `addr`, whose Objective-C type is given by `type`.
///
/// `type` must contain exactly one type code.
///
/// This method must be matched by a subsequent
/// `decodeValue(ofObjCType:at:)` call.
///
/// - Parameters:
/// - type: A type code.
/// - addr: The address of the object to endcode.
open func encodeValue(ofObjCType type: UnsafePointer<Int8>, at addr: UnsafeRawPointer) {
NSRequiresConcreteImplementation()
}
/// Encodes a given `Data` object.
///
/// Subclasses must override this method.
///
/// This method must be matched by a subsequent `decodeData()` call.
///
/// - Parameter data: The data to encode.
open func encode(_ data: Data) {
NSRequiresConcreteImplementation()
}
/// Decodes a single value, whose Objective-C type is given by `type`.
///
/// `type` must contain exactly one type code, and the buffer specified by
/// `data` must be large enough to hold the value corresponding to that type
/// code.
///
/// Subclasses must override this method and provide an implementation to
/// decode the value. In your overriding implementation, decode the value
/// into the buffer beginning at `data`.
///
/// This method matches an `encodeValue(ofObjCType:at:)` call used during
/// encoding.
///
/// - Parameters:
/// - type: A type code.
/// - data: The buffer to put the decoded value into.
open func decodeValue(ofObjCType type: UnsafePointer<Int8>, at data: UnsafeMutableRawPointer) {
NSRequiresConcreteImplementation()
}
/// Decodes and returns a `Data` object that was previously encoded with
/// `encode(_:)`. Subclasses must override this method.
///
/// The implementation of your overriding method must match the
/// implementation of your `encode(_:)` method. For example, a typical
/// `encode(_:)` method encodes the number of bytes of data followed by
/// the bytes themselves. Your override of this method must read the number
/// of bytes, create a `Data` object of the appropriate size, and decode the
/// bytes into the new `Data` object.
///
/// - Returns: The decoded data.
open func decodeData() -> Data? {
NSRequiresConcreteImplementation()
}
/// This method is present for historical reasons and is not used with
/// keyed archivers.
///
/// The version number does apply not to
/// `NSKeyedArchiver`/`NSKeyedUnarchiver`. A keyed archiver does not encode
/// class version numbers.
///
/// - Parameter className: The class name.
/// - Returns: The version in effect for the class named `className` or
/// `NSNotFound` if no class named `className` exists.
open func version(forClassName className: String) -> Int {
NSRequiresConcreteImplementation()
}
open func decodeObject<DecodedObjectType: NSCoding>(of cls: DecodedObjectType.Type, forKey key: String) -> DecodedObjectType? where DecodedObjectType: NSObject {
return decodeObject(of: [cls], forKey: key) as? DecodedObjectType
}
/// Decodes an object for the key, restricted to the specified `classes`.
///
/// This function signature differs from Darwin Foundation in that `classes`
/// is an array of classes, not a set. This is because `AnyClass` cannot
/// be casted to `NSObject`, nor is it `Hashable`.
///
/// - Parameters:
/// - classes: An array of the expected classes.
/// - key: The code key.
/// - Returns: The decoded object.
open func decodeObject(of classes: [AnyClass]?, forKey key: String) -> Any? {
guard allowsKeyedCoding else {
fatalError("This method is only implemented for coders which allowKeyedCoding.")
}
if requiresSecureCoding {
NSRequiresConcreteImplementation()
} else {
return decodeObject(forKey: key)
}
}
// ----- Top-level decoding -----
/*
On Darwin, if a coder's .decodingFailurePolicy is .raiseException, ObjC exceptions are used to interrupt execution of your init(coder:) initializer when a failure occurs during decoding.
The …TopLevel… methods below are documented to:
- interrupt your init(coder:) execution and immediately unwind the stack if a decoding error occurs with your .decodingFailurePolicy set to .raiseException, and
- still return with a thrown error, and continue program execution.
This isn't possible in swift-corelibs-foundation, where ObjC exceptions are unavailable; either program execution is immediately interrupted, or an error is thrown, but not both. To port your code to swift-corelibs-foundations, use the replacements noted below.
*/
@available(*, unavailable, message: "The behavior of this method isn't supported in swift-corelibs-foundation. You can use decodeObject() instead on all platforms. If you would like an error to be thrown, use .decodingFailurePolicy = .setErrorAndReturn, and check the .error property.", renamed: "decodeObject()")
open func decodeTopLevelObject() throws -> Any? {
NSUnsupported()
}
@available(*, unavailable, message: "The behavior of this method isn't supported in swift-corelibs-foundation. You can use decodeObject(forKey:) instead on all platforms. If you would like an error to be thrown, use .decodingFailurePolicy = .setErrorAndReturn, and check the .error property.", renamed: "decodeObject(forKey:)")
open func decodeTopLevelObject(forKey key: String) throws -> Any? {
NSUnsupported()
}
@available(*, unavailable, message: "The behavior of this method isn't supported in swift-corelibs-foundation. You can use decodeObject(of:forKey:) instead on all platforms. If you would like an error to be thrown, use .decodingFailurePolicy = .setErrorAndReturn, and check the .error property.", renamed: "decodeObject(of:forKey:)")
open func decodeTopLevelObject<DecodedObjectType: NSCoding>(of cls: DecodedObjectType.Type, forKey key: String) throws -> DecodedObjectType? where DecodedObjectType: NSObject {
NSUnsupported()
}
/// Decodes an top-level object for the key, restricted to the specified
/// `classes`.
///
/// This function signature differs from Darwin Foundation in that `classes`
/// is an array of classes, not a set. This is because `AnyClass` cannot
/// be casted to `NSObject`, nor is it `Hashable`.
///
/// - Parameters:
/// - classes: An array of the expected classes.
/// - key: The code key.
/// - Returns: The decoded object.
@available(*, unavailable, message: "The behavior of this method isn't supported in swift-corelibs-foundation. You can use decodeObject(of:forKey:) instead on all platforms. If you would like an error to be thrown, use .decodingFailurePolicy = .setErrorAndReturn, and check the .error property.", renamed: "decodeObject(of:forKey:)")
open func decodeTopLevelObject(of classes: [AnyClass], forKey key: String) throws -> Any? {
NSUnsupported()
}
// -----
/// Encodes `object`.
///
/// `NSCoder`’s implementation simply invokes `encodeValue(ofObjCType:at:)`
/// to encode object. Subclasses can override this method to encode
/// a reference to object instead of object itself.
///
/// This method must be matched by a subsequent `decodeObject()` call.
///
/// - Parameter object: The object to encode.
open func encode(_ object: Any?) {
var object = object
withUnsafePointer(to: &object) { (ptr: UnsafePointer<Any?>) -> Void in
encodeValue(ofObjCType: "@", at: UnsafeRawPointer(ptr))
}
}
/// Can be overridden by subclasses to encode an interconnected group of
/// Objective-C objects, starting with `rootObject`.
///
/// `NSCoder`’s implementation simply invokes `encode(_:)`.
///
/// This method must be matched by a subsequent `decodeObject()` call.
///
/// - Parameter rootObject: The root object of the group to encode.
open func encodeRootObject(_ rootObject: Any) {
encode(rootObject)
}
/// Can be overridden by subclasses to encode `anObject` so that a copy,
/// rather than a proxy, is created upon decoding.
///
/// `NSCoder`’s implementation simply invokes `encode(_:)`.
///
/// This method must be matched by a corresponding `decodeObject()` call.
///
/// - Parameter anObject: The object to encode.
open func encodeBycopyObject(_ anObject: Any?) {
encode(anObject)
}
/// Can be overridden by subclasses to encode `anObject` so that a proxy,
/// rather than a copy, is created upon decoding.
///
/// `NSCoder`’s implementation simply invokes `encode(_:)`.
///
/// This method must be matched by a corresponding `decodeObject()` call.
///
/// - Parameter anObject: The object to encode.
open func encodeByrefObject(_ anObject: Any?) {
encode(anObject)
}
/// Can be overridden by subclasses to conditionally encode `object`,
/// preserving common references to that object.
///
/// In the overriding method, `object` should be encoded only if it’s
/// unconditionally encoded elsewhere (with any other `encode...Object`
/// method).
///
/// This method must be matched by a subsequent `decodeObject()` call. Upon
/// decoding, if `object` was never encoded unconditionally,
/// `decodeObject()` returns `nil` in place of `object`. However, if
/// `object` was encoded unconditionally, all references to `object` must be
/// resolved.
///
/// `NSCoder’s` implementation simply invokes `encode(_:)`.
///
/// - Parameter object: The object to conditionally encode.
open func encodeConditionalObject(_ object: Any?) {
encode(object)
}
/// Encodes an array of `count` items, whose Objective-C type is given by
/// `type`.
///
/// The values are encoded from the buffer beginning at `array`. `type` must
/// contain exactly one type code. `NSCoder`’s implementation invokes
/// `encodeValue(ofObjCType:at:)` to encode the entire array of items.
/// Subclasses that implement the `encodeValue(ofObjCType:at:)` method do
/// not need to override this method.
///
/// This method must be matched by a subsequent
/// `decodeArray(ofObjCType:count:at:)` call.
///
/// - note: You should not use this method to encode C arrays of Objective-C
/// objects. See `decodeArray(ofObjCType:count:at:)` for more
/// details.
///
/// - Parameters:
/// - type: A type code.
/// - count: The number of items in `array`.
/// - array: The buffer of items.
open func encodeArray(ofObjCType type: UnsafePointer<Int8>, count: Int, at array: UnsafeRawPointer) {
encodeValue(ofObjCType: "[\(count)\(String(cString: type))]", at: array)
}
/// Encodes a buffer of data whose types are unspecified.
///
/// The buffer to be encoded begins at `byteaddr`, and its length in bytes
/// is given by `length`.
///
/// This method must be matched by a corresponding
/// `decodeBytes(withReturnedLength:)` call.
///
/// - Parameters:
/// - byteaddr: The address of the buffer to encode.
/// - length: The length of the buffer.
open func encodeBytes(_ byteaddr: UnsafeRawPointer?, length: Int) {
var newLength = UInt32(length)
withUnsafePointer(to: &newLength) { (ptr: UnsafePointer<UInt32>) -> Void in
encodeValue(ofObjCType: "I", at: ptr)
}
var empty: [Int8] = []
withUnsafePointer(to: &empty) {
encodeArray(ofObjCType: "c", count: length, at: byteaddr ?? UnsafeRawPointer($0))
}
}
/// Decodes an Objective-C object that was previously encoded with any of
/// the `encode...Object` methods.
///
/// `NSCoder`’s implementation invokes `decodeValue(ofObjCType:at:)` to
/// decode the object data.
///
/// Subclasses may need to override this method if they override any of the
/// corresponding `encode...Object` methods. For example, if an object was
/// encoded conditionally using the `encodeConditionalObject(_:)` method,
/// this method needs to check whether the object had actually been encoded.
///
/// - Returns: The decoded object.
open func decodeObject() -> Any? {
if self.error != nil {
return nil
}
var obj: Any? = nil
withUnsafeMutablePointer(to: &obj) { (ptr: UnsafeMutablePointer<Any?>) -> Void in
decodeValue(ofObjCType: "@", at: UnsafeMutableRawPointer(ptr))
}
return obj
}
open func decodeArray(ofObjCType itemType: UnsafePointer<Int8>, count: Int, at array: UnsafeMutableRawPointer) {
decodeValue(ofObjCType: "[\(count)\(String(cString: itemType))]", at: array)
}
/*
// TODO: This is disabled, as functions which return unsafe interior pointers are inherently unsafe when we have no autorelease pool.
open func decodeBytes(withReturnedLength lengthp: UnsafeMutablePointer<Int>) -> UnsafeMutableRawPointer? {
var length: UInt32 = 0
withUnsafeMutablePointer(to: &length) { (ptr: UnsafeMutablePointer<UInt32>) -> Void in
decodeValue(ofObjCType: "I", at: unsafeBitCast(ptr, to: UnsafeMutableRawPointer.self))
}
// we cannot autorelease here so instead the pending buffers will manage the lifespan of the returned data... this is wasteful but good enough...
let result = UnsafeMutableRawPointer.allocate(byteCount: Int(length), alignment: MemoryLayout<Int>.alignment)
decodeValue(ofObjCType: "c", at: result)
lengthp.pointee = Int(length)
_pendingBuffers.append((result, Int(length)))
return result
}
*/
/// Encodes the property list `aPropertyList`.
///
/// `NSCoder`’s implementation invokes `encodeValue(ofObjCType:at:)`
/// to encode `aPropertyList`.
///
/// This method must be matched by a subsequent `decodePropertyList()` call.
///
/// - Parameter aPropertyList: The property list to encode.
open func encodePropertyList(_ aPropertyList: Any) {
NSRequiresConcreteImplementation()
}
/// Decodes a property list that was previously encoded with
/// `encodePropertyList(_:)`.
///
/// - Returns: The decoded property list.
open func decodePropertyList() -> Any? {
NSRequiresConcreteImplementation()
}
/// The system version in effect for the archive.
///
/// During encoding, the current version. During decoding, the version that
/// was in effect when the data was encoded.
///
/// Subclasses that implement decoding must override this property to return
/// the system version of the data being decoded.
open var systemVersion: UInt32 {
return 1000
}
/// A Boolean value that indicates whether the receiver supports keyed
/// coding of objects.
///
/// `false` by default. Concrete subclasses that support keyed coding,
/// such as `NSKeyedArchiver`, need to override this property to return
/// `true`.
open var allowsKeyedCoding: Bool {
return false
}
/// Encodes the object `objv` and associates it with the string `key`.
///
/// Subclasses must override this method to identify multiple encodings
/// of `objv` and encode a reference to `objv` instead. For example,
/// `NSKeyedArchiver` detects duplicate objects and encodes a reference to
/// the original object rather than encode the same object twice.
///
/// - Parameters:
/// - objv: The object to encode.
/// - key: The key to associate the object with.
open func encode(_ objv: Any?, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Conditionally encodes a reference to `objv` and associates it with
/// the string `key` only if `objv` has been unconditionally encoded with
/// `encode(_:forKey:)`.
///
/// Subclasses must override this method if they support keyed coding.
///
/// The encoded object is decoded with the `decodeObject(forKey:)` method.
/// If `objv` was never encoded unconditionally, `decodeObject(forKey:)`
/// returns `nil` in place of `objv`.
///
/// - Parameters:
/// - objv: The object to conditionally encode.
/// - key: The key to associate the object with.
open func encodeConditionalObject(_ objv: Any?, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Encodes `boolv` and associates it with the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - boolv: The value to encode.
/// - key: The key to associate the value with.
open func encode(_ boolv: Bool, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Encodes the 32-bit integer `intv` and associates it with the string
/// `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - intv: The value to encode.
/// - key: The key to associate the value with.
open func encode(_ intv: Int32, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Encodes the 64-bit integer `intv` and associates it with the string
/// `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - intv: The value to encode.
/// - key: The key to associate the value with.
open func encode(_ intv: Int64, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Encodes `realv` and associates it with the string
/// `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - intv: The value to encode.
/// - key: The key to associate the value with.
open func encode(_ realv: Float, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Encodes `realv` and associates it with the string
/// `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - intv: The value to encode.
/// - key: The key to associate the value with.
open func encode(_ realv: Double, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Encodes a buffer of data, `bytesp`, whose length is specified by `lenv`,
/// and associates it with the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - bytesp: The buffer of data to encode.
/// - lenv: The length of the buffer.
/// - key: The key to associate the data with.
open func encodeBytes(_ bytesp: UnsafePointer<UInt8>?, length lenv: Int, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Returns a Boolean value that indicates whether an encoded value is
/// available for a string.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// The string is passed as `key`.
///
/// - Parameter key: The key to test.
/// - Returns: `true` if an encoded value is available for provided
/// `key`, otherwise `false`.
open func containsValue(forKey key: String) -> Bool {
NSRequiresConcreteImplementation()
}
/// Decodes and returns an Objective-C object that was previously encoded
/// with `encode(_:forKey:)` or `encodeConditionalObject(_:forKey:)` and
/// associated with the string `key`.
///
/// - Parameter key: The key the object to be decoded is associated with.
/// - Returns: The decoded object.
open func decodeObject(forKey key: String) -> Any? {
NSRequiresConcreteImplementation()
}
/// Decodes and returns a Boolean value that was previously encoded with
/// `encode(_:forKey:)` and associated with the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeBool(forKey key: String) -> Bool {
NSRequiresConcreteImplementation()
}
// NOTE: this equivalent to the decodeIntForKey: in Objective-C implementation
/// Decodes and returns an int value that was previously encoded with
/// `encodeCInt(_:forKey:)` or `encode(_:forKey:)` and associated with
/// the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeCInt(forKey key: String) -> Int32 {
NSRequiresConcreteImplementation()
}
/// Decodes and returns a 32-bit integer value that was previously encoded
/// with `encodeCInt(_:forKey:)` or `encode(_:forKey:)` and associated with
/// the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeInt32(forKey key: String) -> Int32 {
NSRequiresConcreteImplementation()
}
/// Decodes and returns a 64-bit integer value that was previously encoded
/// with `encodeCInt(_:forKey:)` or `encode(_:forKey:)` and associated with
/// the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeInt64(forKey key: String) -> Int64 {
NSRequiresConcreteImplementation()
}
/// Decodes and returns a float value that was previously encoded
/// with `encodeCInt(_:forKey:)` or `encode(_:forKey:)` and associated with
/// the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeFloat(forKey key: String) -> Float {
NSRequiresConcreteImplementation()
}
/// Decodes and returns a double value that was previously encoded
/// with `encodeCInt(_:forKey:)` or `encode(_:forKey:)` and associated with
/// the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeDouble(forKey key: String) -> Double {
NSRequiresConcreteImplementation()
}
// TODO: This is disabled, as functions which return unsafe interior pointers are inherently unsafe when we have no autorelease pool.
/*
open func decodeBytes(forKey key: String, returnedLength lengthp: UnsafeMutablePointer<Int>?) -> UnsafePointer<UInt8>? { // returned bytes immutable!
NSRequiresConcreteImplementation()
}
*/
/// - Experiment: This method does not exist in Darwin Foundation. Replaces decodeBytes(forKey:).
@available(swift, deprecated: 9999, renamed: "withDecodedUnsafeBytes(forKey:body:)")
open func withDecodedUnsafeBufferPointer<ResultType>(forKey key: String, body: (UnsafeBufferPointer<UInt8>?) throws -> ResultType) rethrows -> ResultType {
NSRequiresConcreteImplementation()
}
/// - Experiment: This method does not exist in Darwin Foundation. Replaces decodeBytes(forKey:).
open func withDecodedUnsafeBytes<ResultType>(forKey key: String, body: (UnsafeRawBufferPointer?) throws -> ResultType) rethrows -> ResultType {
NSRequiresConcreteImplementation()
}
/// Encodes a given integer number and associates it with a given key.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameters:
/// - intv: The value to encode.
/// - key: The key to associate the value with.
open func encode(_ intv: Int, forKey key: String) {
NSRequiresConcreteImplementation()
}
/// Decodes and returns an integer value that was previously encoded
/// with `encodeCInt(_:forKey:)` or `encode(_:forKey:)` and associated with
/// the string `key`.
///
/// Subclasses must override this method if they perform keyed coding.
///
/// - Parameter key: The key the value to be decoded is associated with.
/// - Returns: The decoded value.
open func decodeInteger(forKey key: String) -> Int {
NSRequiresConcreteImplementation()
}
/// Boolean value that indicates whether the coder requires secure coding.
///
/// `true` if this coder requires secure coding; `false` otherwise.
///
/// Secure coders check a set of allowed classes before decoding objects,
/// and all objects must implement the `NSSecureCoding` protocol.
open var requiresSecureCoding: Bool {
return false
}
/// Returns a decoded property list for the specified key.
///
/// - Parameter key: The coder key.
/// - Returns: A decoded object containing a property list.
open func decodePropertyList(forKey key: String) -> Any? {
NSRequiresConcreteImplementation()
}
/// The array of coded classes allowed for secure coding.
///
/// This property type differs from Darwin Foundation in that `classes` is
/// an array of classes, not a set. This is because `AnyClass` is not
/// `Hashable`.
///
/// - Experiment: This is a draft API currently under consideration for
/// official import into Foundation.
open var allowedClasses: [AnyClass]? {
NSRequiresConcreteImplementation()
}
open func failWithError(_ error: Error) {
if let debugDescription = (error as? NSError)?.userInfo["NSDebugDescription"] {
NSLog("*** NSKeyedUnarchiver.init: \(debugDescription)")
} else {
NSLog("*** NSKeyedUnarchiver.init: decoding error")
}
guard decodingFailurePolicy != .raiseException else {
fatalError("There was a decoding error and the decoding failure policy is .raiseException. Aborting.")
}
_hasFailed = true
}
internal private(set) var _hasFailed = false
open internal(set) var decodingFailurePolicy: NSCoder.DecodingFailurePolicy = .raiseException
open var error: Error? {
NSRequiresConcreteImplementation()
}
internal func _decodeArrayOfObjectsForKey(_ key: String) -> [Any] {
NSRequiresConcreteImplementation()
}
internal func _decodePropertyListForKey(_ key: String) -> Any? {
NSRequiresConcreteImplementation()
}
}