Skip to content

Commit 8aaaec5

Browse files
authored
Use correct start index when accessing Data slices (swiftlang#408)
1 parent 51e0e68 commit 8aaaec5

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

Sources/FoundationEssentials/Data/Data+Writing.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private func writeToFileDescriptorWithProgress(_ fd: Int32, data: Data, reportPr
7575
}
7676
}
7777

78-
var nextRange = 0..<length
78+
var nextRange = data.startIndex..<data.startIndex.advanced(by: length)
7979
var numBytesRemaining = length
8080
while numBytesRemaining > 0 {
8181
if let localProgress, localProgress.isCancelled {
@@ -117,7 +117,7 @@ private func writeToFileDescriptorWithProgress(_ fd: Int32, data: Data, reportPr
117117
break
118118
}
119119

120-
nextRange = numBytesWritten..<data.count
120+
nextRange = nextRange.startIndex.advanced(by: numBytesWritten)..<data.endIndex
121121
}
122122
} while numBytesWritten < 0 && errno == EINTR
123123
}

Tests/FoundationEssentialsTests/DataIOTests.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,17 @@ class DataIOTests : XCTestCase {
4343

4444
func generateTestData() -> Data {
4545
// 16 MB file, big enough to trigger things like chunking
46-
let count = 1 << 24
46+
let count = 16_777_216
4747

4848
let memory = malloc(count)!
4949
let ptr = memory.bindMemory(to: UInt8.self, capacity: count)
5050

5151
// Set a few bytes so we're sure to not be all zeros
5252
let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
53-
for i in 0..<128 {
54-
buf[i] = UInt8.random(in: 1..<42)
53+
for i in 0..<15 {
54+
for j in 0..<128 {
55+
buf[j * 1024 + i] = UInt8.random(in: 1..<42)
56+
}
5557
}
5658

5759
return Data(bytesNoCopy: ptr, count: count, deallocator: .free)
@@ -94,6 +96,25 @@ class DataIOTests : XCTestCase {
9496
try writeAndVerifyTestData(to: url)
9597
cleanup(at: url)
9698
}
99+
100+
func test_slicedReadWrite() throws {
101+
// Be sure to use progress reporting so we get tests of the chunking
102+
let url = testURL()
103+
let data = generateTestData()
104+
let slice = data[data.startIndex.advanced(by: 1 * 1024 * 1024)..<data.startIndex.advanced(by: 8 * 1024 * 1024)]
105+
106+
#if FOUNDATION_FRAMEWORK
107+
let p = Progress(totalUnitCount: 1)
108+
p.becomeCurrent(withPendingUnitCount: 1)
109+
#endif
110+
try slice.write(to: url, options: [])
111+
#if FOUNDATION_FRAMEWORK
112+
p.resignCurrent()
113+
#endif
114+
let readData = try Data(contentsOf: url, options: [])
115+
XCTAssertEqual(readData, slice)
116+
cleanup(at: url)
117+
}
97118

98119
// Atomic writing is a very different code path
99120
func test_readWriteAtomic() throws {

0 commit comments

Comments
 (0)