66module IO ::Stream
77 # A low-level duplex IO adapter that composes distinct readable and writable endpoints.
88 class Duplex
9+ # Initialize a duplex transport from separate readable and writable endpoints.
10+ # @parameter input [IO] The readable endpoint.
11+ # @parameter output [IO] The writable endpoint.
912 def initialize ( input , output = input )
1013 @input = input
1114 @output = output
@@ -14,23 +17,32 @@ def initialize(input, output = input)
1417 attr :input
1518 attr :output
1619
20+ # Return the underlying IO used to represent this duplex stream.
21+ # @returns [IO] The readable endpoint if available, otherwise the writable endpoint.
1722 def to_io
1823 @input || @output
1924 end
2025
26+ # Return the maximum timeout across both endpoints.
27+ # @returns [Numeric | Nil] The effective timeout, or `nil` if no timeout is configured.
2128 def timeout
2229 [ @input . timeout , @output . timeout ] . compact . max
2330 end
2431
32+ # Update the timeout on both endpoints.
33+ # @parameter duration [Numeric | Nil] The timeout to assign.
2534 def timeout = ( duration )
2635 @input . timeout = duration
2736 @output . timeout = duration
2837 end
2938
39+ # Check whether both endpoints are closed.
40+ # @returns [Boolean] True if the duplex stream can no longer read or write.
3041 def closed?
3142 @input . closed? && @output . closed?
3243 end
3344
45+ # Close the readable endpoint.
3446 def close_read
3547 return if @input . closed?
3648
@@ -41,6 +53,7 @@ def close_read
4153 end
4254 end
4355
56+ # Close the writable endpoint.
4457 def close_write
4558 return if @output . closed?
4659
@@ -51,27 +64,44 @@ def close_write
5164 end
5265 end
5366
67+ # Check whether the readable endpoint may still produce data.
68+ # @returns [Boolean] True if the readable endpoint reports it is readable.
5469 def readable?
5570 @input . readable?
5671 end
5772
73+ # Close both endpoints.
5874 def close
5975 @output . close unless @output . closed?
6076 @input . close unless @input . closed?
6177 end
6278
79+ # Write data to the writable endpoint.
80+ # @parameter buffer [String] The data to write.
81+ # @returns [Integer] The number of bytes written.
6382 def write ( buffer )
6483 @output . write ( buffer )
6584 end
6685
86+ # Read data from the readable endpoint without blocking.
87+ # @parameter size [Integer] The maximum number of bytes to read.
88+ # @parameter buffer [String] The destination buffer.
89+ # @parameter exception [Boolean] Whether to raise on `:wait_readable` and EOF conditions.
90+ # @returns [String | Symbol | Nil] Data read from the endpoint, or the underlying non-blocking result.
6791 def read_nonblock ( size , buffer , exception : false )
6892 @input . read_nonblock ( size , buffer , exception : exception )
6993 end
7094
95+ # Wait until the readable endpoint can be read.
96+ # @parameter duration [Numeric | Nil] The maximum time to wait.
97+ # @returns [Boolean] True if the endpoint became readable.
7198 def wait_readable ( duration = @timeout )
7299 @input . wait_readable ( duration )
73100 end
74101
102+ # Wait until the writable endpoint can be written.
103+ # @parameter duration [Numeric | Nil] The maximum time to wait.
104+ # @returns [Boolean] True if the endpoint became writable.
75105 def wait_writable ( duration = @timeout )
76106 @output . wait_writable ( duration )
77107 end
0 commit comments