@@ -55,6 +55,15 @@ public protocol WritableByteStream: class, TextOutputStream {
55
55
56
56
/// Flush the stream's buffer.
57
57
func flush( )
58
+
59
+ /// Signal that the byte stream will not be used further and should be closed.
60
+ func close( ) throws
61
+ }
62
+
63
+ // Default noop implementation of close to avoid source-breaking downstream dependents with the addition of the close
64
+ // API.
65
+ public extension WritableByteStream {
66
+ func close( ) throws { }
58
67
}
59
68
60
69
// Public alias to the old name to not introduce API compatibility.
@@ -184,6 +193,14 @@ public class _WritableByteStreamBase: WritableByteStream {
184
193
// Do nothing.
185
194
}
186
195
196
+ public final func close( ) throws {
197
+ try closeImpl ( )
198
+ }
199
+
200
+ @usableFromInline func closeImpl( ) throws {
201
+ fatalError ( " Subclasses must implement this " )
202
+ }
203
+
187
204
@usableFromInline func writeImpl< C: Collection > ( _ bytes: C ) where C. Iterator. Element == UInt8 {
188
205
fatalError ( " Subclasses must implement this " )
189
206
}
@@ -320,6 +337,12 @@ public final class ThreadSafeOutputByteStream: WritableByteStream {
320
337
stream. writeJSONEscaped ( string)
321
338
}
322
339
}
340
+
341
+ public func close( ) throws {
342
+ try queue. sync {
343
+ try stream. close ( )
344
+ }
345
+ }
323
346
}
324
347
325
348
/// Define an output stream operator. We need it to be left associative, so we
@@ -625,19 +648,24 @@ public final class BufferedOutputByteStream: _WritableByteStreamBase {
625
648
override final func writeImpl( _ bytes: ArraySlice < UInt8 > ) {
626
649
contents += bytes
627
650
}
651
+
652
+ override final func closeImpl( ) throws {
653
+ // Do nothing. The protocol does not require to stop receiving writes, close only signals that resources could
654
+ // be released at this point should we need to.
655
+ }
628
656
}
629
657
630
658
/// Represents a stream which is backed to a file. Not for instantiating.
631
659
public class FileOutputByteStream : _WritableByteStreamBase {
632
660
633
- /// Closes the file flushing any buffered data.
634
- public final func close( ) throws {
661
+ public override final func closeImpl( ) throws {
635
662
flush ( )
636
- try closeImpl ( )
663
+ try fileCloseImpl ( )
637
664
}
638
665
639
- func closeImpl( ) throws {
640
- fatalError ( " closeImpl() should be implemented by a subclass " )
666
+ /// Closes the file flushing any buffered data.
667
+ func fileCloseImpl( ) throws {
668
+ fatalError ( " fileCloseImpl() should be implemented by a subclass " )
641
669
}
642
670
}
643
671
@@ -726,7 +754,7 @@ public final class LocalFileOutputByteStream: FileOutputByteStream {
726
754
fflush ( filePointer)
727
755
}
728
756
729
- override final func closeImpl ( ) throws {
757
+ override final func fileCloseImpl ( ) throws {
730
758
defer {
731
759
fclose ( filePointer)
732
760
// If clients called close we shouldn't call fclose again in deinit.
0 commit comments