Skip to content

Commit c3b0db7

Browse files
authored
fix: StreamableHttpBody with sliced Data (#859)
1 parent 2bad0b9 commit c3b0db7

File tree

2 files changed

+39
-25
lines changed

2 files changed

+39
-25
lines changed

Diff for: Sources/SmithyStreams/StreamableHttpBody.swift

+8-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import enum Smithy.StreamError
1616
/// It acts as a bridge between AWS SDK and CRT.
1717
public class StreamableHttpBody: IStreamable {
1818

19+
/// The index of the data being transferred.
20+
///
21+
/// When the body is `.data`, `position` is the index of the next byte to be transferred
22+
/// (note that the startIndex of `Data` need not be zero if the Data is a "slice" of some other Data.)
23+
/// When the body is `.stream`, `position` is the number of bytes from the start of the stream.
1924
var position: Data.Index
2025
let body: ByteStream
2126
let logger: SwiftLogger
@@ -82,10 +87,8 @@ public class StreamableHttpBody: IStreamable {
8287
public func read(buffer: UnsafeMutableBufferPointer<UInt8>) throws -> Int? {
8388
switch body {
8489
case .data(let data):
85-
guard let data = data else {
86-
return nil
87-
}
88-
let toRead = min(buffer.count, data.count - position)
90+
guard let data = data else { return nil }
91+
let toRead = min(buffer.count, data.endIndex - position)
8992
data.copyBytes(to: buffer, from: position..<position.advanced(by: toRead))
9093
position = position.advanced(by: toRead)
9194
logger.debug("read \(toRead) bytes from data")
@@ -94,9 +97,7 @@ public class StreamableHttpBody: IStreamable {
9497
}
9598
return toRead
9699
case .stream(let stream):
97-
guard let data = try stream.read(upToCount: buffer.count) else {
98-
return nil
99-
}
100+
guard let data = try stream.read(upToCount: buffer.count) else { return nil }
100101
data.copyBytes(to: buffer, from: data.startIndex..<data.endIndex)
101102
position = position.advanced(by: data.count)
102103
logger.debug("read \(data.count) bytes from stream")

Diff for: Tests/ClientRuntimeTests/NetworkingTests/Streaming/StreamableHttpBodyTests.swift

+31-18
Original file line numberDiff line numberDiff line change
@@ -12,60 +12,73 @@ import AwsCommonRuntimeKit
1212

1313
final class StreamableHttpBodyTests: XCTestCase {
1414

15-
let testData = Data([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A])
15+
let testData = Data([
16+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
17+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A
18+
])
1619

17-
func testRead() throws {
18-
let sut = StreamableHttpBody(body: .data(testData))
20+
func test_streamWholeData() throws {
21+
try read(data: Data(testData[..<11]))
22+
try seek(data: Data(testData[11...]))
23+
}
24+
25+
func test_streamSlicedData() throws {
26+
try read(data: testData[..<11])
27+
try seek(data: testData[11...])
28+
}
29+
30+
private func read(data: Data, file: StaticString = #file, line: UInt = #line) throws {
31+
let sut = StreamableHttpBody(body: .data(data))
1932

2033
// read first 4 bytes
2134
let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 4)
2235
let bytesRead1 = try sut.read(buffer: buffer)
2336
let bytes1 = Data(bytes: buffer.baseAddress!, count: bytesRead1!)
24-
XCTAssertEqual(bytesRead1, 4)
25-
XCTAssertEqual(bytes1, Data([0x00, 0x01, 0x02, 0x03]))
37+
XCTAssertEqual(bytesRead1, 4, file: file, line: line)
38+
XCTAssertEqual(bytes1, Data([0x00, 0x01, 0x02, 0x03]), file: file, line: line)
2639

2740
// read next 4 bytes from current position
2841
let bytesRead2 = try sut.read(buffer: buffer)
2942
let bytes2 = Data(bytes: buffer.baseAddress!, count: bytesRead2!)
30-
XCTAssertEqual(bytesRead2, 4)
31-
XCTAssertEqual(bytes2, Data([0x04, 0x05, 0x06, 0x07]))
43+
XCTAssertEqual(bytesRead2, 4, file: file, line: line)
44+
XCTAssertEqual(bytes2, Data([0x04, 0x05, 0x06, 0x07]), file: file, line: line)
3245

3346
// read next 4 bytes from current position
3447
// this should only read 3 bytes since we are at the end of the stream
3548
let bytesRead3 = try sut.read(buffer: buffer)
3649
let bytes3 = Data(bytes: buffer.baseAddress!, count: bytesRead3!)
37-
XCTAssertEqual(bytesRead3, 3)
38-
XCTAssertEqual(bytes3, Data([0x08, 0x09, 0x0A]))
50+
XCTAssertEqual(bytesRead3, 3, file: file, line: line)
51+
XCTAssertEqual(bytes3, Data([0x08, 0x09, 0x0A]), file: file, line: line)
3952

4053
// read next 4 bytes from current position
4154
// this should return nil since we are at the end of the stream
4255
let bytesRead4 = try sut.read(buffer: buffer)
43-
XCTAssertNil(bytesRead4)
56+
XCTAssertNil(bytesRead4, file: file, line: line)
4457
}
4558

46-
func testSeek() throws {
47-
let sut = StreamableHttpBody(body: .data(testData))
59+
private func seek(data: Data, file: StaticString = #file, line: UInt = #line) throws {
60+
let sut = StreamableHttpBody(body: .data(data))
4861

4962
// read first 4 bytes
5063
let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 4)
5164
let bytesRead1 = try sut.read(buffer: buffer)
5265
let bytes1 = Data(bytes: buffer.baseAddress!, count: bytesRead1!)
53-
XCTAssertEqual(bytesRead1!, 4)
54-
XCTAssertEqual(bytes1, Data([0x00, 0x01, 0x02, 0x03]))
66+
XCTAssertEqual(bytesRead1!, 4, file: file, line: line)
67+
XCTAssertEqual(bytes1, Data([0x00, 0x01, 0x02, 0x03]), file: file, line: line)
5568

5669
// seek to offset 2 and read 4 bytes
5770
try sut.seek(offset: 2, streamSeekType: .begin)
5871
let bytesRead2 = try sut.read(buffer: buffer)
5972
let bytes2 = Data(bytes: buffer.baseAddress!, count: bytesRead2!)
60-
XCTAssertEqual(bytesRead2!, 4)
61-
XCTAssertEqual(bytes2, Data([0x02, 0x03, 0x04, 0x05]))
73+
XCTAssertEqual(bytesRead2!, 4, file: file, line: line)
74+
XCTAssertEqual(bytes2, Data([0x02, 0x03, 0x04, 0x05]), file: file, line: line)
6275

6376
// seek to offset 8 and read 3 bytes
6477
// this should only read 3 bytes since we are at the end of the stream
6578
try sut.seek(offset: 8, streamSeekType: .begin)
6679
let bytesRead3 = try sut.read(buffer: buffer)
6780
let bytes3 = Data(bytes: buffer.baseAddress!, count: bytesRead3!)
68-
XCTAssertEqual(bytesRead3!, 3)
69-
XCTAssertEqual(bytes3, Data([0x08, 0x09, 0x0A]))
81+
XCTAssertEqual(bytesRead3!, 3, file: file, line: line)
82+
XCTAssertEqual(bytes3, Data([0x08, 0x09, 0x0A]), file: file, line: line)
7083
}
7184
}

0 commit comments

Comments
 (0)