Last active
April 15, 2022 03:47
-
-
Save reitzig/29d38b948812454a8dedc00a9f61f44f to your computer and use it in GitHub Desktop.
Reading InputStream into Data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Data { | |
/** | |
Consumes the specified input stream, creating a new Data object | |
with its content. | |
- Parameter reading: The input stream to read data from. | |
- Note: Closes the specified stream. | |
*/ | |
init(reading input: InputStream) { | |
self.init() | |
input.open() | |
let bufferSize = 1024 | |
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize) | |
while input.hasBytesAvailable { | |
let read = input.read(buffer, maxLength: bufferSize) | |
self.append(buffer, count: read) | |
} | |
buffer.deallocate() | |
input.close() | |
} | |
/** | |
Consumes the specified input stream for up to `byteCount` bytes, | |
creating a new Data object with its content. | |
- Parameter reading: The input stream to read data from. | |
- Parameter byteCount: The maximum number of bytes to read from `reading`. | |
- Note: Does _not_ close the specified stream. | |
*/ | |
init(reading input: InputStream, for byteCount: Int) { | |
self.init() | |
input.open() | |
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: byteCount) | |
let read = input.read(buffer, maxLength: byteCount) | |
self.append(buffer, count: read) | |
buffer.deallocate() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import XCTest | |
class DataTests: XCTestCase { | |
func testInitFromStream() { | |
// Tests some random values, plus the empty case | |
[[UInt8](), | |
[0b00001001], | |
[0b01000000, 0b01001011], | |
[0b01011110, 0b11101111, 0b00011001], | |
[0b01101100, 0b00101010, 0b10111001, 0b10000111], | |
[0b00011011, 0b00010111, 0b00011000, 0b01100100, 0b10110000], | |
[UInt8](repeating: 77, count: 2049) // something large; 2*buffersize + 1 | |
].forEach { (bytes) in | |
let referenceData = Data(bytes) | |
let stream = InputStream(data: referenceData) | |
XCTAssertEqual(Data(reading: stream), referenceData) | |
} | |
} | |
func testInitFromStreamWithMaxLength() { | |
// Tests some random values, plus the empty case | |
[[UInt8](), | |
[0b00001001], | |
[0b01000000, 0b01001011], | |
[0b01011110, 0b11101111, 0b00011001], | |
[0b01101100, 0b00101010, 0b10111001, 0b10000111] | |
].forEach { (bytes) in | |
let referenceData = Data(bytes) | |
let stream = InputStream(data: referenceData) | |
defer { stream.close() } | |
XCTAssertEqual( | |
Data(reading: stream, for: 3), | |
referenceData[0..<(min(3, referenceData.count))] | |
) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sorry, I completely missed your comment! Do we not get notifications here?
Did you solve the issue? I'm not sure I understand fully what the problem is; I'd recommend you open a question on Stack Overflow!
That said, I don't think the function I've written is suitable for reading from streams that are "slow". At least I never tried it on such.