Skip to content

Commit d4a7047

Browse files
committed
Parity: Stream
- Fix the base class to work like it does on Darwin. - Allow scheduling input and output streams. - Allow setting and retrieving properties.
1 parent fc4a6cc commit d4a7047

File tree

2 files changed

+65
-32
lines changed

2 files changed

+65
-32
lines changed

Foundation/Stream.swift

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ extension Stream {
6262
open class Stream: NSObject {
6363

6464
public override init() {
65-
65+
if type(of: self) == Stream.self {
66+
NSRequiresConcreteImplementation()
67+
}
6668
}
6769

6870
open func open() {
@@ -77,21 +79,19 @@ open class Stream: NSObject {
7779
// By default, a stream is its own delegate, and subclassers of InputStream and OutputStream must maintain this contract. [someStream setDelegate:nil] must restore this behavior. As usual, delegates are not retained.
7880

7981
open func property(forKey key: PropertyKey) -> AnyObject? {
80-
NSUnimplemented()
82+
NSRequiresConcreteImplementation()
8183
}
8284

8385
open func setProperty(_ property: AnyObject?, forKey key: PropertyKey) -> Bool {
84-
NSUnimplemented()
86+
NSRequiresConcreteImplementation()
8587
}
8688

87-
// Re-enable once run loop is compiled on all platforms
88-
8989
open func schedule(in aRunLoop: RunLoop, forMode mode: RunLoop.Mode) {
90-
NSUnimplemented()
90+
NSRequiresConcreteImplementation()
9191
}
9292

9393
open func remove(from aRunLoop: RunLoop, forMode mode: RunLoop.Mode) {
94-
NSUnimplemented()
94+
NSRequiresConcreteImplementation()
9595
}
9696

9797
open var streamStatus: Status {
@@ -132,6 +132,10 @@ open class InputStream: Stream {
132132
return CFReadStreamHasBytesAvailable(_stream)
133133
}
134134

135+
fileprivate init(readStream: CFReadStream) {
136+
_stream = readStream
137+
}
138+
135139
public init(data: Data) {
136140
_stream = CFReadStreamCreateWithData(kCFAllocatorSystemDefault, data._cfObject)
137141
}
@@ -159,14 +163,30 @@ open class InputStream: Stream {
159163
open override var streamError: Error? {
160164
return CFReadStreamCopyError(_stream)
161165
}
166+
167+
open override func property(forKey key: PropertyKey) -> AnyObject? {
168+
return CFReadStreamCopyProperty(_stream, key.rawValue._cfObject)
169+
}
170+
171+
open override func setProperty(_ property: AnyObject?, forKey key: PropertyKey) -> Bool {
172+
return CFReadStreamSetProperty(_stream, key.rawValue._cfObject, property)
173+
}
174+
175+
open override func schedule(in aRunLoop: RunLoop, forMode mode: RunLoop.Mode) {
176+
CFReadStreamScheduleWithRunLoop(_stream, aRunLoop.getCFRunLoop(), mode.rawValue._cfObject)
177+
}
178+
179+
open override func remove(from aRunLoop: RunLoop, forMode mode: RunLoop.Mode) {
180+
CFReadStreamUnscheduleFromRunLoop(_stream, aRunLoop.getCFRunLoop(), mode.rawValue._cfObject)
181+
}
162182
}
163183

164184
// OutputStream is an abstract class representing the base functionality of a write stream.
165185
// Subclassers are required to implement these methods.
166186
// Currently this is left as named OutputStream due to conflicts with the standard library's text streaming target protocol named OutputStream (which ideally should be renamed)
167187
open class OutputStream : Stream {
168188

169-
private var _stream: CFWriteStream!
189+
private var _stream: CFWriteStream!
170190

171191
// writes the bytes from the specified buffer to the stream up to len bytes. Returns the number of bytes actually written.
172192
open func write(_ buffer: UnsafePointer<UInt8>, maxLength len: Int) -> Int {
@@ -177,6 +197,11 @@ open class OutputStream : Stream {
177197
open var hasSpaceAvailable: Bool {
178198
return CFWriteStreamCanAcceptBytes(_stream)
179199
}
200+
201+
fileprivate init(writeStream: CFWriteStream) {
202+
_stream = writeStream
203+
}
204+
180205
// NOTE: on Darwin this is 'open class func toMemory() -> Self'
181206
required public init(toMemory: ()) {
182207
_stream = CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault, kCFAllocatorDefault)
@@ -216,13 +241,21 @@ open class OutputStream : Stream {
216241
return CFWriteStreamCopyProperty(_stream, key.rawValue._cfObject)
217242
}
218243

219-
open override func setProperty(_ property: AnyObject?, forKey key: PropertyKey) -> Bool {
244+
open override func setProperty(_ property: AnyObject?, forKey key: PropertyKey) -> Bool {
220245
return CFWriteStreamSetProperty(_stream, key.rawValue._cfObject, property)
221246
}
222247

223248
open override var streamError: Error? {
224249
return CFWriteStreamCopyError(_stream)
225250
}
251+
252+
open override func schedule(in aRunLoop: RunLoop, forMode mode: RunLoop.Mode) {
253+
CFWriteStreamScheduleWithRunLoop(_stream, aRunLoop.getCFRunLoop(), mode.rawValue._cfObject)
254+
}
255+
256+
open override func remove(from aRunLoop: RunLoop, forMode mode: RunLoop.Mode) {
257+
CFWriteStreamUnscheduleFromRunLoop(_stream, aRunLoop.getCFRunLoop(), mode.rawValue._cfObject)
258+
}
226259
}
227260

228261
public struct _InputStreamSPIForFoundationNetworkingUseOnly {
@@ -278,13 +311,13 @@ extension InputStream {
278311
#if false
279312
extension Stream {
280313
open class func getStreamsToHost(withName hostname: String, port: Int, inputStream: AutoreleasingUnsafeMutablePointer<InputStream?>?, outputStream: AutoreleasingUnsafeMutablePointer<OutputStream?>?) {
281-
NSUnimplemented()
314+
NSUnsupported()
282315
}
283316
}
284317

285318
extension Stream {
286319
open class func getBoundStreams(withBufferSize bufferSize: Int, inputStream: AutoreleasingUnsafeMutablePointer<InputStream?>?, outputStream: AutoreleasingUnsafeMutablePointer<OutputStream?>?) {
287-
NSUnimplemented()
320+
NSUnsupported()
288321
}
289322
}
290323
#endif

TestFoundation/TestStream.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,6 @@ private extension Data {
3434
}
3535

3636
class TestStream : XCTestCase {
37-
static var allTests: [(String, (TestStream) -> () throws -> Void)] {
38-
var tests: [(String, (TestStream) -> () throws -> Void)] = [
39-
("test_InputStreamWithData", test_InputStreamWithData),
40-
("test_InputStreamWithUrl", test_InputStreamWithUrl),
41-
("test_InputStreamWithFile", test_InputStreamWithFile),
42-
("test_InputStreamHasBytesAvailable", test_InputStreamHasBytesAvailable),
43-
("test_InputStreamInvalidPath", test_InputStreamInvalidPath),
44-
("test_outputStreamCreationToFile", test_outputStreamCreationToFile),
45-
("test_outputStreamCreationToBuffer", test_outputStreamCreationToBuffer),
46-
("test_outputStreamCreationWithUrl", test_outputStreamCreationWithUrl),
47-
("test_outputStreamCreationToMemory", test_outputStreamCreationToMemory),
48-
("test_outputStreamHasSpaceAvailable", test_outputStreamHasSpaceAvailable),
49-
("test_ouputStreamWithInvalidPath", test_ouputStreamWithInvalidPath),
50-
]
51-
52-
#if NS_FOUNDATION_ALLOWS_TESTABLE_IMPORT
53-
tests.append(("test_InputStreamSeekToPosition", test_InputStreamSeekToPosition))
54-
#endif
55-
return tests
56-
}
57-
5837
func test_InputStreamWithData(){
5938
let message: NSString = "Hello, playground"
6039
let messageData: Data = message.data(using: String.Encoding.utf8.rawValue)!
@@ -285,6 +264,27 @@ class TestStream : XCTestCase {
285264
XCTAssertEqual(.error, outputStream!.streamStatus)
286265
}
287266

267+
static var allTests: [(String, (TestStream) -> () throws -> Void)] {
268+
var tests: [(String, (TestStream) -> () throws -> Void)] = [
269+
("test_InputStreamWithData", test_InputStreamWithData),
270+
("test_InputStreamWithUrl", test_InputStreamWithUrl),
271+
("test_InputStreamWithFile", test_InputStreamWithFile),
272+
("test_InputStreamHasBytesAvailable", test_InputStreamHasBytesAvailable),
273+
("test_InputStreamInvalidPath", test_InputStreamInvalidPath),
274+
("test_outputStreamCreationToFile", test_outputStreamCreationToFile),
275+
("test_outputStreamCreationToBuffer", test_outputStreamCreationToBuffer),
276+
("test_outputStreamCreationWithUrl", test_outputStreamCreationWithUrl),
277+
("test_outputStreamCreationToMemory", test_outputStreamCreationToMemory),
278+
("test_outputStreamHasSpaceAvailable", test_outputStreamHasSpaceAvailable),
279+
("test_ouputStreamWithInvalidPath", test_ouputStreamWithInvalidPath),
280+
]
281+
282+
#if NS_FOUNDATION_ALLOWS_TESTABLE_IMPORT
283+
tests.append(("test_InputStreamSeekToPosition", test_InputStreamSeekToPosition))
284+
#endif
285+
return tests
286+
}
287+
288288
private func createTestFile(_ path: String, _contents: Data) -> String? {
289289
let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
290290
do {

0 commit comments

Comments
 (0)