@@ -61,37 +61,84 @@ internal final class _SwiftNSData : NSData, _SwiftNativeFoundationType {
61
61
super. init ( bytes: dummyPointer, length: 0 , copy: false , deallocator: nil )
62
62
}
63
63
64
- required convenience init ? ( coder aDecoder: NSCoder ) {
65
- fatalError ( " init(coder:) has not been implemented " )
66
- }
67
-
68
- required convenience init ( ) {
69
- self . init ( immutableObject: NSData ( ) )
64
+ public required convenience init ? ( coder aDecoder: NSCoder ) {
65
+ fatalError ( " init(coder:) should not be called on _SwiftNSData " )
70
66
}
71
67
72
68
deinit {
73
69
releaseWrappedObject ( )
74
70
}
75
71
76
- // MARK: - Funnel overrides
77
- override var length : Int {
72
+
73
+ override
74
+ var length : Int {
78
75
get {
79
76
return _mapUnmanaged { $0. length }
80
77
}
81
78
}
82
- override var bytes : UnsafeRawPointer {
79
+
80
+ override
81
+ var bytes : UnsafeRawPointer {
83
82
return _mapUnmanaged { $0. bytes }
84
83
}
84
+
85
+ override
86
+ func subdata( with range: NSRange ) -> Data {
87
+ return _mapUnmanaged { $0. subdata ( with: range) }
88
+ }
89
+
90
+ override
91
+ func getBytes( _ buffer: UnsafeMutableRawPointer , length: Int ) {
92
+ return _mapUnmanaged { $0. getBytes ( buffer, length: length) }
93
+ }
94
+
95
+ override
96
+ func getBytes( _ buffer: UnsafeMutableRawPointer , range: NSRange ) {
97
+ return _mapUnmanaged { $0. getBytes ( buffer, range: range) }
98
+ }
99
+
100
+ override
101
+ func isEqual( to other: Data ) -> Bool {
102
+ return _mapUnmanaged { return $0. isEqual ( to: other) }
103
+ }
104
+
105
+ override
106
+ func write( to url: URL , options: Data . WritingOptions ) throws {
107
+ return try _mapUnmanaged { try $0. write ( to: url, options: options) }
108
+ }
109
+
110
+ override
111
+ open func range( of dataToFind: Data , options mask: SearchOptions = [ ] , in searchRange: NSRange ) -> NSRange {
112
+ return _mapUnmanaged {
113
+ return $0. range ( of: dataToFind, options: mask, in: searchRange)
114
+ }
115
+ }
116
+
117
+ override
118
+ func enumerateBytes( _ block: ( UnsafeRawPointer , NSRange , UnsafeMutablePointer < ObjCBool > ) -> Void ) {
119
+ return _mapUnmanaged { $0. enumerateBytes ( block) }
120
+ }
121
+
122
+ override
123
+ func base64EncodedString( options: Data . Base64EncodingOptions ) -> String {
124
+ return _mapUnmanaged { $0. base64EncodedString ( options: options) }
125
+ }
126
+
127
+ override
128
+ func base64EncodedData( options: Data . Base64EncodingOptions ) -> Data {
129
+ return _mapUnmanaged { $0. base64EncodedData ( options: options) }
130
+ }
85
131
}
86
132
133
+
87
134
/**
88
135
`Data` is a `MutableCollection` of bytes.
89
136
90
137
This type provides "copy-on-write" behavior, and is also bridged to the Objective-C `NSData` class. You can wrap an instance of a custom subclass of `NSData` in `struct Data` by converting it using `myData as Data`.
91
138
92
- `Data` can be initialized with an `UnsafeRawPointer` and count, an array of `UInt8` (the primitive byte type), an `UnsafeBufferPointer`,the contents of a file, or base-64 encoded data or strings. The buffer-oriented functions provide an extra measure of safety by automatically performing the size calculation, as the type is known at compile time.
139
+ `Data` can be initialized with an `UnsafeRawPointer` and count, an array of `UInt8` (the primitive byte type), an `UnsafeBufferPointer`, the contents of a file, or base-64 encoded data or strings. The buffer-oriented functions provide an extra measure of safety by automatically performing the size calculation, as the type is known at compile time.
93
140
*/
94
- public struct Data : ReferenceConvertible , CustomStringConvertible , Equatable , Hashable , RandomAccessCollection , MutableCollection , _MutablePairBoxing {
141
+ public struct Data : ReferenceConvertible , Equatable , Hashable , RandomAccessCollection , MutableCollection , RangeReplaceableCollection , _MutablePairBoxing {
95
142
/// The Objective-C bridged type of `Data`.
96
143
public typealias ReferenceType = NSData
97
144
@@ -166,7 +213,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
166
213
/// Initialize a `Data` with the contents of an Array.
167
214
///
168
215
/// - parameter bytes: An array of bytes to copy.
169
- public init ( bytes: [ UInt8 ] ) {
216
+ public init ( bytes: Array < UInt8 > ) {
170
217
_wrapped = bytes. withUnsafeBufferPointer {
171
218
return _SwiftNSData ( immutableObject: NSData ( bytes: $0. baseAddress, length: $0. count) )
172
219
}
@@ -198,6 +245,18 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
198
245
}
199
246
}
200
247
248
+ /// Initialize a `Data` with the specified count of zeroed bytes.
249
+ ///
250
+ /// - parameter count: The number of bytes the data initially contains.
251
+ public init ( count: Int ) {
252
+ if let d = NSMutableData ( length: count) {
253
+ _wrapped = _SwiftNSData ( mutableObject: d)
254
+ } else {
255
+ fatalError ( " Unable to allocate data of the requested count " )
256
+ }
257
+ }
258
+
259
+
201
260
/// Initialize an empty `Data`.
202
261
public init ( ) {
203
262
_wrapped = _SwiftNSData ( immutableObject: NSData ( bytes: nil , length: 0 ) )
@@ -249,18 +308,6 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
249
308
return nil
250
309
}
251
310
}
252
-
253
- /// Initialize a `Data` with the specified count of zeroed bytes.
254
- ///
255
- /// - parameter count: The number of bytes the data initially contains.
256
- public init ( count: Int ) {
257
- if let d = NSMutableData ( length: count) {
258
- _wrapped = _SwiftNSData ( mutableObject: d)
259
- } else {
260
- fatalError ( " Unable to allocate data of the requested count " )
261
- }
262
- }
263
-
264
311
265
312
/// Initialize a `Data` by adopting a reference type.
266
313
///
@@ -270,8 +317,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
270
317
///
271
318
/// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
272
319
public init ( referencing reference: NSData ) {
273
- // NOTE: don't fix this warning on Darwin -- linux will complain
274
- _wrapped = _SwiftNSData ( immutableObject: reference. copy ( ) as! AnyObject )
320
+ _wrapped = _SwiftNSData ( immutableObject: reference. copy ( ) as! NSObject )
275
321
}
276
322
277
323
// -----------------------------------
@@ -315,7 +361,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
315
361
let mutableBytes = _getUnsafeMutableBytesPointer ( )
316
362
defer { _fixLifetime ( self ) }
317
363
let contentPtr = mutableBytes. bindMemory ( to: ContentType . self, capacity: count / MemoryLayout< ContentType> . stride)
318
- return try body ( contentPtr)
364
+ return try body ( UnsafeMutablePointer ( contentPtr) )
319
365
}
320
366
321
367
// MARK: -
@@ -330,7 +376,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
330
376
_mapUnmanaged { $0. getBytes ( pointer, length: count) }
331
377
}
332
378
333
- private func _copyBytesHelper( to pointer: UnsafeMutablePointer < UInt8 > , from range: NSRange ) {
379
+ private func _copyBytesHelper( to pointer: UnsafeMutableRawPointer , from range: NSRange ) {
334
380
_mapUnmanaged { $0. getBytes ( pointer, range: range) }
335
381
}
336
382
@@ -371,10 +417,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
371
417
guard !copyRange. isEmpty else { return 0 }
372
418
373
419
let nsRange = NSMakeRange ( copyRange. lowerBound, copyRange. upperBound - copyRange. lowerBound)
374
- let ptr = buffer. baseAddress!
375
- ptr. withMemoryRebound ( to: UInt8 . self, capacity: buffer. count) {
376
- _copyBytesHelper ( to: $0, from: nsRange)
377
- }
420
+ _copyBytesHelper ( to: buffer. baseAddress!, from: nsRange)
378
421
return copyRange. count
379
422
}
380
423
@@ -387,7 +430,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
387
430
/// - throws: An error in the Cocoa domain, if there is an error writing to the `URL`.
388
431
public func write( to url: URL , options: Data . WritingOptions = [ ] ) throws {
389
432
try _mapUnmanaged {
390
- try $0. write ( to: url, options: WritingOptions ( rawValue : options. rawValue ) )
433
+ try $0. write ( to: url, options: options)
391
434
}
392
435
}
393
436
@@ -502,7 +545,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
502
545
let bufferCount = buffer. count * MemoryLayout< SourceType> . stride
503
546
504
547
_applyUnmanagedMutation {
505
- $0. replaceBytes ( in: nsRange, withBytes: buffer. baseAddress! , length: bufferCount)
548
+ $0. replaceBytes ( in: nsRange, withBytes: buffer. baseAddress, length: bufferCount)
506
549
}
507
550
508
551
}
@@ -514,7 +557,8 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
514
557
/// - precondition: The bounds of `subrange` must be valid indices of the collection.
515
558
/// - parameter subrange: The range in the data to replace.
516
559
/// - parameter newElements: The replacement bytes.
517
- public mutating func replaceSubrange< ByteCollection : Collection > ( _ subrange: Range < Index > , with newElements: ByteCollection ) where ByteCollection. Iterator. Element == Data . Iterator . Element {
560
+ public mutating func replaceSubrange< ByteCollection : Collection > ( _ subrange: Range < Index > , with newElements: ByteCollection )
561
+ where ByteCollection. Iterator. Element == Data . Iterator . Element {
518
562
519
563
// Calculate this once, it may not be O(1)
520
564
let replacementCount : Int = numericCast ( newElements. count)
@@ -587,16 +631,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
587
631
return _mapUnmanaged { $0. hashValue }
588
632
}
589
633
590
- /// A human-readable description for the data.
591
- public var description : String {
592
- return _mapUnmanaged { $0. description }
593
- }
594
-
595
- /// A human-readable debug description for the data.
596
- public var debugDescription : String {
597
- return _mapUnmanaged { $0. debugDescription }
598
- }
599
-
634
+ // MARK: -
600
635
601
636
// MARK: -
602
637
// MARK: Index and Subscript
@@ -650,33 +685,117 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
650
685
///
651
686
/// The iterator will increment byte-by-byte.
652
687
public func makeIterator( ) -> Data . Iterator {
653
- return IndexingIterator ( _elements : self )
688
+ return Iterator ( _data : self )
654
689
}
690
+
691
+ public struct Iterator : IteratorProtocol {
692
+ private let _data : Data
693
+ private typealias Buffer = (
694
+ UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 ,
695
+ UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 ,
696
+ UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 ,
697
+ UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 )
698
+ private var _buffer : Buffer
699
+ private var _idx : Data . Index
700
+ private let _endIdx : Data . Index
701
+
702
+ fileprivate init ( _data: Data ) {
703
+ self . _data = _data
704
+ _buffer = ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )
705
+ _idx = 0
706
+ _endIdx = _data. endIndex
707
+ }
708
+
709
+ public mutating func next( ) -> UInt8 ? {
710
+ guard _idx < _endIdx else { return nil }
711
+ defer { _idx += 1 }
712
+
713
+ let bufferSize = MemoryLayout< Buffer> . size
714
+ return withUnsafeMutablePointer ( to: & _buffer) { ptr_ in
715
+ let ptr = UnsafeMutableRawPointer ( ptr_) . assumingMemoryBound ( to: UInt8 . self)
716
+ let bufferIdx = _idx % bufferSize
717
+ if bufferIdx == 0 {
718
+ // populate the buffer
719
+ _data. copyBytes ( to: ptr, from: _idx..< ( _endIdx - _idx > bufferSize ? _idx + bufferSize : _endIdx) )
720
+ }
721
+ return ptr [ bufferIdx]
722
+ }
723
+ }
724
+ }
725
+
726
+ // MARK: -
727
+ //
728
+
729
+ @available ( * , unavailable, renamed: " count " )
730
+ public var length : Int {
731
+ get { fatalError ( ) }
732
+ set { fatalError ( ) }
733
+ }
734
+
735
+ @available ( * , unavailable, message: " use withUnsafeBytes instead " )
736
+ public var bytes : UnsafeRawPointer { fatalError ( ) }
655
737
738
+ @available ( * , unavailable, message: " use withUnsafeMutableBytes instead " )
739
+ public var mutableBytes : UnsafeMutableRawPointer { fatalError ( ) }
740
+
656
741
/// Returns `true` if the two `Data` arguments are equal.
657
742
public static func == ( d1 : Data , d2 : Data ) -> Bool {
658
743
return d1. _wrapped. isEqual ( to: d2)
659
744
}
660
745
}
661
746
747
+ extension Data : CustomStringConvertible , CustomDebugStringConvertible , CustomReflectable {
748
+ /// A human-readable description for the data.
749
+ public var description : String {
750
+ return " \( self . count) bytes "
751
+ }
752
+
753
+ /// A human-readable debug description for the data.
754
+ public var debugDescription : String {
755
+ return self . description
756
+ }
662
757
758
+ public var customMirror : Mirror {
759
+ let nBytes = self . count
760
+ var children : [ ( label: String ? , value: Any ) ] = [ ]
761
+ children. append ( ( label: " count " , value: nBytes) )
762
+
763
+ self . withUnsafeBytes { ( bytes : UnsafePointer < UInt8 > ) in
764
+ children. append ( ( label: " pointer " , value: bytes) )
765
+ }
766
+
767
+ // Minimal size data is output as an array
768
+ if nBytes < 64 {
769
+ children. append ( ( label: " bytes " , value: self [ 0 ..< nBytes] . map { $0 } ) )
770
+ }
771
+
772
+ let m = Mirror ( self , children: children, displayStyle: Mirror . DisplayStyle. struct)
773
+ return m
774
+ }
775
+ }
776
+
777
+ extension Data {
778
+ @available ( * , unavailable, renamed: " copyBytes(to:count:) " )
779
+ public func getBytes( _ buffer: UnsafeMutableRawPointer , length: Int ) { }
780
+
781
+ @available ( * , unavailable, renamed: " copyBytes(to:from:) " )
782
+ public func getBytes( _ buffer: UnsafeMutableRawPointer , range: NSRange ) { }
783
+ }
663
784
664
785
/// Provides bridging functionality for struct Data to class NSData and vice-versa.
665
786
extension Data : _ObjectTypeBridgeable {
666
- public static func _isBridgedToObjectiveC( ) -> Bool {
667
- return true
668
- }
669
-
670
787
@_semantics ( " convertToObjectiveC " )
671
788
public func _bridgeToObjectiveC( ) -> NSData {
672
789
return unsafeBitCast ( _wrapped, to: NSData . self)
673
790
}
674
791
675
792
public static func _forceBridgeFromObjectiveC( _ input: NSData , result: inout Data ? ) {
793
+ // We must copy the input because it might be mutable; just like storing a value type in ObjC
676
794
result = Data ( referencing: input)
677
795
}
678
796
679
797
public static func _conditionallyBridgeFromObjectiveC( _ input: NSData , result: inout Data ? ) -> Bool {
798
+ // We must copy the input because it might be mutable; just like storing a value type in ObjC
680
799
result = Data ( referencing: input)
681
800
return true
682
801
}
@@ -687,3 +806,12 @@ extension Data : _ObjectTypeBridgeable {
687
806
return result!
688
807
}
689
808
}
809
+
810
+ extension NSData : _HasCustomAnyHashableRepresentation {
811
+ // Must be @nonobjc to avoid infinite recursion during bridging.
812
+ @nonobjc
813
+ public func _toCustomAnyHashable( ) -> AnyHashable ? {
814
+ return AnyHashable ( Data ( referencing: self ) )
815
+ }
816
+ }
817
+
0 commit comments