Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename OutputStream to OutputStreamable [SE-0086] #3576

Merged
merged 2 commits into from
Jul 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/StringDesign.rst
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ Building
.. sidebar:: ``append``

the ``append`` method is a consequence of ``String``\ 's
conformance to ``OutputStream``. See the *Swift
conformance to ``TextOutputStream``. See the *Swift
formatting proposal* for details.

:Swift:
Expand Down
54 changes: 27 additions & 27 deletions docs/TextFormatting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,18 @@ Design Details
Output Streams
..............

The most fundamental part of this design is ``OutputStream``, a thing
The most fundamental part of this design is ``TextOutputStream``, a thing
into which we can stream text: [#character1]_

::

protocol OutputStream {
protocol TextOutputStream {
func append(_ text: String)
}

Every ``String`` can be used as an ``OutputStream`` directly::
Every ``String`` can be used as an ``TextOutputStream`` directly::

extension String : OutputStream {
extension String : TextOutputStream {
func append(_ text: String)
}

Expand All @@ -142,7 +142,7 @@ need to declare conformance: simply give the type a ``debugFormat()``::

Because ``String`` is a ``Streamable``, your implementation of
``debugFormat`` can just return a ``String``. If want to write
directly to the ``OutputStream`` for efficiency reasons,
directly to the ``TextOutputStream`` for efficiency reasons,
(e.g. if your representation is huge), you can return a custom
``DebugRepresentation`` type.

Expand Down Expand Up @@ -197,11 +197,11 @@ implement::
Because it's not always efficient to construct a ``String``
representation before writing an object to a stream, we provide a
``Streamable`` protocol, for types that can write themselves into an
``OutputStream``. Every ``Streamable`` is also a ``CustomStringConvertible``,
``TextOutputStream``. Every ``Streamable`` is also a ``CustomStringConvertible``,
naturally::

protocol Streamable : CustomStringConvertible {
func writeTo<T: OutputStream>(_ target: [inout] T)
func writeTo<T: TextOutputStream>(_ target: [inout] T)

// You'll never want to reimplement this
func format() -> PrintRepresentation {
Expand All @@ -224,7 +224,7 @@ adds surrounding quotes and escapes special characters::
struct EscapedStringRepresentation : Streamable {
var _value: String

func writeTo<T: OutputStream>(_ target: [inout] T) {
func writeTo<T: TextOutputStream>(_ target: [inout] T) {
target.append("\"")
for c in _value {
target.append(c.escape())
Expand All @@ -233,11 +233,11 @@ adds surrounding quotes and escapes special characters::
}
}

Besides modeling ``OutputStream``, ``String`` also conforms to
Besides modeling ``TextOutputStream``, ``String`` also conforms to
``Streamable``::

extension String : Streamable {
func writeTo<T: OutputStream>(_ target: [inout] T) {
func writeTo<T: TextOutputStream>(_ target: [inout] T) {
target.append(self) // Append yourself to the stream
}

Expand Down Expand Up @@ -275,12 +275,12 @@ complicated ``format(…)`` might be written::
struct RadixFormat<T: CustomStringConvertibleInteger> : Streamable {
var value: T, radix = 10, fill = " ", width = 0

func writeTo<S: OutputStream>(_ target: [inout] S) {
func writeTo<S: TextOutputStream>(_ target: [inout] S) {
_writeSigned(value, &target)
}

// Write the given positive value to stream
func _writePositive<T:CustomStringConvertibleInteger, S: OutputStream>(
func _writePositive<T:CustomStringConvertibleInteger, S: TextOutputStream>(
_ value: T, stream: [inout] S
) -> Int {
if value == 0 { return 0 }
Expand All @@ -293,7 +293,7 @@ complicated ``format(…)`` might be written::
return nDigits + 1
}

func _writeSigned<T:CustomStringConvertibleInteger, S: OutputStream>(
func _writeSigned<T:CustomStringConvertibleInteger, S: TextOutputStream>(
_ value: T, target: [inout] S
) {
var width = 0
Expand Down Expand Up @@ -333,15 +333,15 @@ considerable thought, they are included here for completeness and to
ensure our proposed design doesn't rule out important directions of
evolution.

``OutputStream`` Adapters
``TextOutputStream`` Adapters
.........................

Most text transformations can be expressed as adapters over generic
``OutputStream``\ s. For example, it's easy to imagine an upcasing
``TextOutputStream``\ s. For example, it's easy to imagine an upcasing
adapter that transforms its input to upper case before writing it to
an underlying stream::

struct UpperStream<UnderlyingStream:OutputStream> : OutputStream {
struct UpperStream<UnderlyingStream:TextOutputStream> : TextOutputStream {
func append(_ x: String) { base.append(x.toUpper()) }
var base: UnderlyingStream
}
Expand All @@ -353,26 +353,26 @@ processed and written to the underlying stream:

.. parsed-literal::

struct TrimStream<UnderlyingStream:OutputStream> : OutputStream {
struct TrimStream<UnderlyingStream:TextOutputStream> : TextOutputStream {
func append(_ x: String) { ... }
**func close() { ... }**
var base: UnderlyingStream
var bufferedWhitespace: String
}

This makes general ``OutputStream`` adapters more complicated to write
and use than ordinary ``OutputStream``\ s.
This makes general ``TextOutputStream`` adapters more complicated to write
and use than ordinary ``TextOutputStream``\ s.

``Streamable`` Adapters
.......................

For every conceivable ``OutputStream`` adaptor there's a corresponding
For every conceivable ``TextOutputStream`` adaptor there's a corresponding
``Streamable`` adaptor. For example::

struct UpperStreamable<UnderlyingStreamable:Streamable> {
var base: UnderlyingStreamable

func writeTo<T: OutputStream>(_ target: [inout] T) {
func writeTo<T: TextOutputStream>(_ target: [inout] T) {
var adaptedStream = UpperStream(target)
self.base.writeTo(&adaptedStream)
target = adaptedStream.base
Expand Down Expand Up @@ -418,20 +418,20 @@ least until we do, we opt not to trade away any CPU, memory, and
power.

If we were willing to say that only ``class``\ es can conform to
``OutputStream``, we could eliminate the explicit ``[inout]`` where
``OutputStream``\ s are passed around. Then, we'd simply need a
``TextOutputStream``, we could eliminate the explicit ``[inout]`` where
``TextOutputStream``\ s are passed around. Then, we'd simply need a
``class StringStream`` for creating ``String`` representations. It
would also make ``OutputStream`` adapters a *bit* simpler to use
would also make ``TextOutputStream`` adapters a *bit* simpler to use
because you'd never need to "write back" explicitly onto the target
stream. However, stateful ``OutputStream`` adapters would still need a
stream. However, stateful ``TextOutputStream`` adapters would still need a
``close()`` method, which makes a perfect place to return a copy of
the underlying stream, which can then be "written back":

.. parsed-literal::

struct AdaptedStreamable<T:Streamable> {
...
func writeTo<Target: OutputStream>(_ target: [inout] Target) {
func writeTo<Target: TextOutputStream>(_ target: [inout] Target) {
// create the stream that transforms the representation
var adaptedTarget = adapt(target, adapter);
// write the Base object to the target stream
Expand All @@ -444,7 +444,7 @@ the underlying stream, which can then be "written back":
}

We think anyone writing such adapters can handle the need for explicit
write-back, and the ability to use ``String`` as an ``OutputStream``
write-back, and the ability to use ``String`` as an ``TextOutputStream``
without additionally allocating a ``StringStream`` on the heap seems
to tip the balance in favor of the current design.

Expand Down
4 changes: 2 additions & 2 deletions stdlib/private/SwiftPrivate/IO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public struct _FDInputStream {
}
}

public struct _Stderr : OutputStream {
public struct _Stderr : TextOutputStream {
public init() {}

public mutating func write(_ string: String) {
Expand All @@ -91,7 +91,7 @@ public struct _Stderr : OutputStream {
}
}

public struct _FDOutputStream : OutputStream {
public struct _FDOutputStream : TextOutputStream {
public let fd: CInt
public var isClosed: Bool = false

Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/DebuggerSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public enum _DebuggerSupport {
}
}

internal static func printForDebuggerImpl<StreamType : OutputStream>(
internal static func printForDebuggerImpl<StreamType : TextOutputStream>(
value: Any?,
mirror: Mirror,
name: String?,
Expand Down
53 changes: 28 additions & 25 deletions stdlib/public/core/OutputStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import SwiftShims
///
/// You can send the output of the standard library's `print(_:to:)` and
/// `dump(_:to:)` functions to an instance of a type that conforms to the
/// `OutputStream` protocol instead of to standard output. Swift's `String`
/// type conforms to `OutputStream` already, so you can capture the output
/// `TextOutputStream` protocol instead of to standard output. Swift's `String`
/// type conforms to `TextOutputStream` already, so you can capture the output
/// from `print(_:to:)` and `dump(_:to:)` in a string instead of logging it to
/// standard output.
///
Expand All @@ -31,18 +31,18 @@ import SwiftShims
/// }
/// // s == "12345"
///
/// Conforming to the OutputStream Protocol
/// Conforming to the TextOutputStream Protocol
/// =======================================
///
/// To make your custom type conform to the `OutputStream` protocol, implement
/// the required `write(_:)` method. Functions that use an `OutputStream`
/// To make your custom type conform to the `TextOutputStream` protocol, implement
/// the required `write(_:)` method. Functions that use an `TextOutputStream`
/// target may call `write(_:)` multiple times per writing operation.
///
/// As an example, here's an implementation of an output stream that converts
/// any input to its plain ASCII representation before sending it to standard
/// output.
///
/// struct ASCIILogger: OutputStream {
/// struct ASCIILogger: TextOutputStream {
/// mutating func write(_ string: String) {
/// let ascii = string.unicodeScalars.lazy.map { scalar in
/// scalar == "\n"
Expand All @@ -65,23 +65,26 @@ import SwiftShims
/// var asciiLogger = ASCIILogger()
/// print(s, to: &asciiLogger)
/// // Prints "Hearts \u{2661} and Diamonds \u{2662}"
public protocol OutputStream {
public protocol TextOutputStream {
mutating func _lock()
mutating func _unlock()

/// Appends the given string to the stream.
mutating func write(_ string: String)
}

extension OutputStream {
/// Temporary typealias
public typealias OutputStream = TextOutputStream

extension TextOutputStream {
public mutating func _lock() {}
public mutating func _unlock() {}
}

/// A source of text-streaming operations.
///
/// Instances of types that conform to the `Streamable` protocol can write
/// their value to instances of any type that conforms to the `OutputStream`
/// their value to instances of any type that conforms to the `TextOutputStream`
/// protocol. The Swift standard library's text-related types, `String`,
/// `Character`, and `UnicodeScalar`, all conform to `Streamable`.
///
Expand All @@ -94,7 +97,7 @@ extension OutputStream {
public protocol Streamable {
/// Writes a textual representation of this instance into the given output
/// stream.
func write<Target : OutputStream>(to target: inout Target)
func write<Target : TextOutputStream>(to target: inout Target)
}

/// A type with a customized textual representation.
Expand Down Expand Up @@ -229,7 +232,7 @@ func _getEnumCaseName<T>(_ value: T) -> UnsafePointer<CChar>?
func _opaqueSummary(_ metadata: Any.Type) -> UnsafePointer<CChar>?

/// Do our best to print a value that cannot be printed directly.
internal func _adHocPrint_unlocked<T, TargetStream : OutputStream>(
internal func _adHocPrint_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ mirror: Mirror, _ target: inout TargetStream,
isDebugPrint: Bool
) {
Expand Down Expand Up @@ -316,7 +319,7 @@ internal func _adHocPrint_unlocked<T, TargetStream : OutputStream>(

@inline(never)
@_semantics("stdlib_binary_only")
internal func _print_unlocked<T, TargetStream : OutputStream>(
internal func _print_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ target: inout TargetStream
) {
// Optional has no representation suitable for display; therefore,
Expand Down Expand Up @@ -372,7 +375,7 @@ func _toStringReadOnlyPrintable<T : CustomStringConvertible>(_ x: T) -> String {
//===----------------------------------------------------------------------===//

@inline(never)
public func _debugPrint_unlocked<T, TargetStream : OutputStream>(
public func _debugPrint_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ target: inout TargetStream
) {
if let debugPrintableObject = value as? CustomDebugStringConvertible {
Expand All @@ -394,7 +397,7 @@ public func _debugPrint_unlocked<T, TargetStream : OutputStream>(
_adHocPrint_unlocked(value, mirror, &target, isDebugPrint: true)
}

internal func _dumpPrint_unlocked<T, TargetStream : OutputStream>(
internal func _dumpPrint_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ mirror: Mirror, _ target: inout TargetStream
) {
if let displayStyle = mirror.displayStyle {
Expand Down Expand Up @@ -463,7 +466,7 @@ internal func _dumpPrint_unlocked<T, TargetStream : OutputStream>(
// OutputStreams
//===----------------------------------------------------------------------===//

internal struct _Stdout : OutputStream {
internal struct _Stdout : TextOutputStream {
mutating func _lock() {
_swift_stdlib_flockfile_stdout()
}
Expand All @@ -489,7 +492,7 @@ internal struct _Stdout : OutputStream {
}
}

extension String : OutputStream {
extension String : TextOutputStream {
/// Appends the given string to this string.
///
/// - Parameter other: A string to append.
Expand All @@ -506,7 +509,7 @@ extension String : Streamable {
/// Writes the string into the given output stream.
///
/// - Parameter target: An output stream.
public func write<Target : OutputStream>(to target: inout Target) {
public func write<Target : TextOutputStream>(to target: inout Target) {
target.write(self)
}
}
Expand All @@ -515,7 +518,7 @@ extension Character : Streamable {
/// Writes the character into the given output stream.
///
/// - Parameter target: An output stream.
public func write<Target : OutputStream>(to target: inout Target) {
public func write<Target : TextOutputStream>(to target: inout Target) {
target.write(String(self))
}
}
Expand All @@ -525,7 +528,7 @@ extension UnicodeScalar : Streamable {
/// output stream.
///
/// - Parameter target: An output stream.
public func write<Target : OutputStream>(to target: inout Target) {
public func write<Target : TextOutputStream>(to target: inout Target) {
target.write(String(Character(self)))
}
}
Expand All @@ -534,9 +537,9 @@ extension UnicodeScalar : Streamable {
public var _playgroundPrintHook : ((String) -> Void)? = {_ in () }

internal struct _TeeStream<
L : OutputStream,
R : OutputStream
> : OutputStream {
L : TextOutputStream,
R : TextOutputStream
> : TextOutputStream {
var left: L
var right: R

Expand All @@ -548,12 +551,12 @@ internal struct _TeeStream<
mutating func _unlock() { right._unlock(); left._unlock() }
}

@available(*, unavailable, renamed: "OutputStream")
public typealias OutputStreamType = OutputStream
@available(*, unavailable, renamed: "TextOutputStream")
public typealias OutputStreamType = TextOutputStream

extension Streamable {
@available(*, unavailable, renamed: "write(to:)")
public func writeTo<Target : OutputStream>(_ target: inout Target) {
public func writeTo<Target : TextOutputStream>(_ target: inout Target) {
Builtin.unreachable()
}
}
Loading