Skip to content

Commit 3b7d7c8

Browse files
authored
Assorted minor data updates (#1564)
* Replace inline buffer with withUnsafeTemporaryAllocation * Fix Darwin build * Move deprecated APIs off of internal implementations * Move copyBytes(to:) implementation to DataProtocol file * Don't calculate buffer length twice * Align Data mirror children size with Array
1 parent cc94421 commit 3b7d7c8

File tree

5 files changed

+74
-84
lines changed

5 files changed

+74
-84
lines changed

Sources/FoundationEssentials/Data/Data+Deprecated.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extension Data {
3333
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
3434
@available(swift, deprecated: 5, message: "use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead")
3535
public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
36-
return try _representation.withUnsafeBytes {
36+
return try self.withUnsafeBytes {
3737
return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafePointer<ContentType>(bitPattern: 0xBAD0)!)
3838
}
3939
}
@@ -44,7 +44,7 @@ extension Data {
4444
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
4545
@available(swift, deprecated: 5, message: "use `withUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R` instead")
4646
public mutating func withUnsafeMutableBytes<ResultType, ContentType>(_ body: (UnsafeMutablePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
47-
return try _representation.withUnsafeMutableBytes {
47+
return try self.withUnsafeMutableBytes {
4848
return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafeMutablePointer<ContentType>(bitPattern: 0xBAD0)!)
4949
}
5050
}
@@ -55,6 +55,9 @@ extension Data {
5555
/// - parameter block: The closure to invoke for each region of data. You may stop the enumeration by setting the `stop` parameter to `true`.
5656
@available(swift, deprecated: 5, message: "use `regions` or `for-in` instead")
5757
public func enumerateBytes(_ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Index, _ stop: inout Bool) -> Void) {
58-
_representation.enumerateBytes(block)
58+
self.withUnsafeBytes {
59+
var stop = false
60+
block($0.assumingMemoryBound(to: UInt8.self), 0, &stop)
61+
}
5962
}
6063
}

Sources/FoundationEssentials/Data/Data.swift

Lines changed: 8 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -106,25 +106,10 @@ internal func _withStackOrHeapBuffer(capacity: Int, _ body: (UnsafeMutableBuffer
106106
body(UnsafeMutableBufferPointer(start: nil, count: 0))
107107
return
108108
}
109-
typealias InlineBuffer = ( // 32 bytes
110-
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
111-
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
112-
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
113-
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8
114-
)
115-
let inlineCount = MemoryLayout<InlineBuffer>.size
116-
if capacity <= inlineCount {
117-
var buffer: InlineBuffer = (
118-
0, 0, 0, 0, 0, 0, 0, 0,
119-
0, 0, 0, 0, 0, 0, 0, 0,
120-
0, 0, 0, 0, 0, 0, 0, 0,
121-
0, 0, 0, 0, 0, 0, 0, 0
122-
)
123-
withUnsafeMutableBytes(of: &buffer) { buffer in
124-
assert(buffer.count == inlineCount)
125-
buffer.withMemoryRebound(to: UInt8.self) {
126-
body(UnsafeMutableBufferPointer(start: $0.baseAddress, count: capacity))
127-
}
109+
// Use an inline allocation for 32 bytes or fewer
110+
if capacity <= 32 {
111+
withUnsafeTemporaryAllocation(of: UInt8.self, capacity: capacity) { buffer in
112+
body(buffer)
128113
}
129114
return
130115
}
@@ -493,63 +478,6 @@ public struct Data : RandomAccessCollection, MutableCollection, RangeReplaceable
493478
return try _representation.withUnsafeMutableBytes(body)
494479
}
495480

496-
// MARK: -
497-
// MARK: Copy Bytes
498-
499-
/// Copy the contents of the data to a pointer.
500-
///
501-
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
502-
/// - parameter count: The number of bytes to copy.
503-
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
504-
@inlinable // This is @inlinable as trivially forwarding.
505-
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
506-
precondition(count >= 0, "count of bytes to copy must not be negative")
507-
if count == 0 { return }
508-
_copyBytesHelper(to: UnsafeMutableRawPointer(pointer), from: startIndex..<(startIndex + count))
509-
}
510-
511-
@inlinable // This is @inlinable as trivially forwarding.
512-
internal func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
513-
if range.isEmpty { return }
514-
_representation.copyBytes(to: pointer, from: range)
515-
}
516-
517-
/// Copy a subset of the contents of the data to a pointer.
518-
///
519-
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
520-
/// - parameter range: The range in the `Data` to copy.
521-
/// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes.
522-
@inlinable // This is @inlinable as trivially forwarding.
523-
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, from range: Range<Index>) {
524-
_copyBytesHelper(to: pointer, from: range)
525-
}
526-
527-
// Copy the contents of the data into a buffer.
528-
///
529-
/// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout<DestinationType>.stride * buffer.count` then the first N bytes will be copied into the buffer.
530-
/// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called.
531-
/// - parameter buffer: A buffer to copy the data into.
532-
/// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied.
533-
/// - returns: Number of bytes copied into the destination buffer.
534-
@inlinable // This is @inlinable as generic and reasonably small.
535-
public func copyBytes<DestinationType>(to buffer: UnsafeMutableBufferPointer<DestinationType>, from range: Range<Index>? = nil) -> Int {
536-
let cnt = count
537-
guard cnt > 0 else { return 0 }
538-
539-
let copyRange : Range<Index>
540-
if let r = range {
541-
guard !r.isEmpty else { return 0 }
542-
copyRange = r.lowerBound..<(r.lowerBound + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, r.upperBound - r.lowerBound))
543-
} else {
544-
copyRange = startIndex..<(startIndex + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, cnt))
545-
}
546-
547-
guard !copyRange.isEmpty else { return 0 }
548-
549-
_copyBytesHelper(to: buffer.baseAddress!, from: copyRange)
550-
return copyRange.upperBound - copyRange.lowerBound
551-
}
552-
553481
// MARK: -
554482

555483
@inlinable // This is @inlinable as a generic, trivially forwarding function.
@@ -887,7 +815,8 @@ extension Data : Equatable {
887815
}
888816

889817
// Compare the contents
890-
return memcmp(b1Address, b2Address, b2.count) == 0
818+
assert(length1 == b2.count)
819+
return memcmp(b1Address, b2Address, length1) == 0
891820
}
892821
}
893822
}
@@ -917,8 +846,8 @@ extension Data : CustomStringConvertible, CustomDebugStringConvertible, CustomRe
917846
}
918847

919848
// Minimal size data is output as an array
920-
if nBytes < 64 {
921-
children.append((label: "bytes", value: Array(self[startIndex..<Swift.min(nBytes + startIndex, endIndex)])))
849+
if nBytes < 256 {
850+
children.append((label: "bytes", value: Array(self)))
922851
}
923852

924853
let m = Mirror(self, children:children, displayStyle: Mirror.DisplayStyle.struct)

Sources/FoundationEssentials/Data/DataProtocol.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,60 @@ extension Data : MutableDataProtocol {
239239
public var regions: CollectionOfOne<Data> {
240240
return CollectionOfOne(self)
241241
}
242+
243+
/// Copy the contents of the data to a pointer.
244+
///
245+
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
246+
/// - parameter count: The number of bytes to copy.
247+
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
248+
@inlinable // This is @inlinable as trivially forwarding.
249+
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
250+
precondition(count >= 0, "count of bytes to copy must not be negative")
251+
if count == 0 { return }
252+
_copyBytesHelper(to: UnsafeMutableRawPointer(pointer), from: startIndex..<(startIndex + count))
253+
}
254+
255+
@inlinable // This is @inlinable as trivially forwarding.
256+
internal func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
257+
if range.isEmpty { return }
258+
_representation.copyBytes(to: pointer, from: range)
259+
}
260+
261+
/// Copy a subset of the contents of the data to a pointer.
262+
///
263+
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
264+
/// - parameter range: The range in the `Data` to copy.
265+
/// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes.
266+
@inlinable // This is @inlinable as trivially forwarding.
267+
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, from range: Range<Index>) {
268+
_copyBytesHelper(to: pointer, from: range)
269+
}
270+
271+
// Copy the contents of the data into a buffer.
272+
///
273+
/// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout<DestinationType>.stride * buffer.count` then the first N bytes will be copied into the buffer.
274+
/// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called.
275+
/// - parameter buffer: A buffer to copy the data into.
276+
/// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied.
277+
/// - returns: Number of bytes copied into the destination buffer.
278+
@inlinable // This is @inlinable as generic and reasonably small.
279+
public func copyBytes<DestinationType>(to buffer: UnsafeMutableBufferPointer<DestinationType>, from range: Range<Index>? = nil) -> Int {
280+
let cnt = count
281+
guard cnt > 0 else { return 0 }
282+
283+
let copyRange : Range<Index>
284+
if let r = range {
285+
guard !r.isEmpty else { return 0 }
286+
copyRange = r.lowerBound..<(r.lowerBound + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, r.upperBound - r.lowerBound))
287+
} else {
288+
copyRange = startIndex..<(startIndex + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, cnt))
289+
}
290+
291+
guard !copyRange.isEmpty else { return 0 }
292+
293+
_copyBytesHelper(to: buffer.baseAddress!, from: copyRange)
294+
return copyRange.upperBound - copyRange.lowerBound
295+
}
242296
}
243297

244298
//===--- DataProtocol Conditional Conformances ----------------------------===//

Sources/FoundationEssentials/Data/Representations/Data+Inline.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#if canImport(Glibc)
13+
#if canImport(Darwin)
14+
import Darwin
15+
#elseif canImport(Glibc)
1416
@preconcurrency import Glibc
1517
#elseif canImport(Musl)
1618
@preconcurrency import Musl

Sources/FoundationEssentials/Data/Representations/DataStorage.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#if canImport(Glibc)
13+
#if canImport(Darwin)
14+
import Darwin
15+
#elseif canImport(Glibc)
1416
@preconcurrency import Glibc
1517
#elseif canImport(Musl)
1618
@preconcurrency import Musl

0 commit comments

Comments
 (0)