Skip to content

Commit 2ccec68

Browse files
authored
Re-import a few things for struct Data (#583)
There was a missing protocol and a few overrides that didnt come in right before
1 parent 66fad9f commit 2ccec68

File tree

1 file changed

+178
-50
lines changed

1 file changed

+178
-50
lines changed

Foundation/Data.swift

Lines changed: 178 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -61,37 +61,84 @@ internal final class _SwiftNSData : NSData, _SwiftNativeFoundationType {
6161
super.init(bytes: dummyPointer, length: 0, copy: false, deallocator: nil)
6262
}
6363

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")
7066
}
7167

7268
deinit {
7369
releaseWrappedObject()
7470
}
7571

76-
// MARK: - Funnel overrides
77-
override var length : Int {
72+
73+
override
74+
var length : Int {
7875
get {
7976
return _mapUnmanaged { $0.length }
8077
}
8178
}
82-
override var bytes : UnsafeRawPointer {
79+
80+
override
81+
var bytes : UnsafeRawPointer {
8382
return _mapUnmanaged { $0.bytes }
8483
}
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+
}
85131
}
86132

133+
87134
/**
88135
`Data` is a `MutableCollection` of bytes.
89136

90137
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`.
91138

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.
93140
*/
94-
public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, _MutablePairBoxing {
141+
public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, _MutablePairBoxing {
95142
/// The Objective-C bridged type of `Data`.
96143
public typealias ReferenceType = NSData
97144

@@ -166,7 +213,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
166213
/// Initialize a `Data` with the contents of an Array.
167214
///
168215
/// - parameter bytes: An array of bytes to copy.
169-
public init(bytes: [UInt8]) {
216+
public init(bytes: Array<UInt8>) {
170217
_wrapped = bytes.withUnsafeBufferPointer {
171218
return _SwiftNSData(immutableObject: NSData(bytes: $0.baseAddress, length: $0.count))
172219
}
@@ -198,6 +245,18 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
198245
}
199246
}
200247

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+
201260
/// Initialize an empty `Data`.
202261
public init() {
203262
_wrapped = _SwiftNSData(immutableObject: NSData(bytes: nil, length: 0))
@@ -249,18 +308,6 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
249308
return nil
250309
}
251310
}
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-
264311

265312
/// Initialize a `Data` by adopting a reference type.
266313
///
@@ -270,8 +317,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
270317
///
271318
/// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
272319
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)
275321
}
276322

277323
// -----------------------------------
@@ -315,7 +361,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
315361
let mutableBytes = _getUnsafeMutableBytesPointer()
316362
defer { _fixLifetime(self)}
317363
let contentPtr = mutableBytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
318-
return try body(contentPtr)
364+
return try body(UnsafeMutablePointer(contentPtr))
319365
}
320366

321367
// MARK: -
@@ -330,7 +376,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
330376
_mapUnmanaged { $0.getBytes(pointer, length: count) }
331377
}
332378

333-
private func _copyBytesHelper(to pointer: UnsafeMutablePointer<UInt8>, from range: NSRange) {
379+
private func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: NSRange) {
334380
_mapUnmanaged { $0.getBytes(pointer, range: range) }
335381
}
336382

@@ -371,10 +417,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
371417
guard !copyRange.isEmpty else { return 0 }
372418

373419
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)
378421
return copyRange.count
379422
}
380423

@@ -387,7 +430,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
387430
/// - throws: An error in the Cocoa domain, if there is an error writing to the `URL`.
388431
public func write(to url: URL, options: Data.WritingOptions = []) throws {
389432
try _mapUnmanaged {
390-
try $0.write(to: url, options: WritingOptions(rawValue: options.rawValue))
433+
try $0.write(to: url, options: options)
391434
}
392435
}
393436

@@ -502,7 +545,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
502545
let bufferCount = buffer.count * MemoryLayout<SourceType>.stride
503546

504547
_applyUnmanagedMutation {
505-
$0.replaceBytes(in: nsRange, withBytes: buffer.baseAddress!, length: bufferCount)
548+
$0.replaceBytes(in: nsRange, withBytes: buffer.baseAddress, length: bufferCount)
506549
}
507550

508551
}
@@ -514,7 +557,8 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
514557
/// - precondition: The bounds of `subrange` must be valid indices of the collection.
515558
/// - parameter subrange: The range in the data to replace.
516559
/// - 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 {
518562

519563
// Calculate this once, it may not be O(1)
520564
let replacementCount : Int = numericCast(newElements.count)
@@ -587,16 +631,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
587631
return _mapUnmanaged { $0.hashValue }
588632
}
589633

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: -
600635

601636
// MARK: -
602637
// MARK: Index and Subscript
@@ -650,33 +685,117 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
650685
///
651686
/// The iterator will increment byte-by-byte.
652687
public func makeIterator() -> Data.Iterator {
653-
return IndexingIterator(_elements: self)
688+
return Iterator(_data: self)
654689
}
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() }
655737

738+
@available(*, unavailable, message: "use withUnsafeMutableBytes instead")
739+
public var mutableBytes: UnsafeMutableRawPointer { fatalError() }
740+
656741
/// Returns `true` if the two `Data` arguments are equal.
657742
public static func ==(d1 : Data, d2 : Data) -> Bool {
658743
return d1._wrapped.isEqual(to: d2)
659744
}
660745
}
661746

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+
}
662757

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+
}
663784

664785
/// Provides bridging functionality for struct Data to class NSData and vice-versa.
665786
extension Data : _ObjectTypeBridgeable {
666-
public static func _isBridgedToObjectiveC() -> Bool {
667-
return true
668-
}
669-
670787
@_semantics("convertToObjectiveC")
671788
public func _bridgeToObjectiveC() -> NSData {
672789
return unsafeBitCast(_wrapped, to: NSData.self)
673790
}
674791

675792
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
676794
result = Data(referencing: input)
677795
}
678796

679797
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
680799
result = Data(referencing: input)
681800
return true
682801
}
@@ -687,3 +806,12 @@ extension Data : _ObjectTypeBridgeable {
687806
return result!
688807
}
689808
}
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

Comments
 (0)