Skip to content

Align the behavior of SSLSocket's IO-compatible methods with core IO - #1104

Open
rhenium wants to merge 9 commits into
ruby:masterfrom
rhenium:ky/ssl-io-methods-updates
Open

Align the behavior of SSLSocket's IO-compatible methods with core IO#1104
rhenium wants to merge 9 commits into
ruby:masterfrom
rhenium:ky/ssl-io-methods-updates

Conversation

@rhenium

@rhenium rhenium commented Sep 2, 2026

Copy link
Copy Markdown
Member

Update the following methods on OpenSSL::Buffering for better consistency with IO in modern Ruby:

  • #ungetc: Accept strings.
  • #each_byte: Return Enumerator if called without a block.
  • #gets: Really complex method and had many issues. I've tried to match the behavior as closely as possible.
  • #write, #<<, #syswrite, #write_nonblock: Convert arguments with to_s rather than to_str.
  • #each_char, #puts, #ungetbyte: Added missing methods.

Also run the same tests against actual IO objects to catch accidental discrepancy.

The Buffer class is an implementation detail.

It will be removed once ruby/openssl starts to require Ruby 3.4 or
later, where String#append_as_bytes is always available.
Allow OpenSSL::Buffering#ungetc to take String, not just Integer.

Add OpenSSL::Buffering#ungetbyte with the consistent behavior with
IO#ungetbyte in Ruby >= 1.9.
Let OpenSSL::Buffering#each_byte return an Enumerator if called without
a block.

Add the #each_char variant for compatibility with Ruby 1.9 IO.
Rewrite OpenSSL::Buffering#gets to handle parameters as closely to core
IO as possible. This includes changes:

  - Add support for the calling form"gets(limit), where the rs is
    omitted.
  - Add support for rs=nil (slurp mode).
  - Add support for rs="" (paragraph mode).
  - Enforce limit correctly when EOF is reached before rs.
  - Do not attempt to read from the socket when limit=0 is passed.
  - Let #each_line, #readlines, and #readline forward all arguments to
    #gets, not just the rs.
IO#write and IO#<< convert the arguments to String with #to_s.
OpenSSL::Buffering#write also documented the intended behavior, but the
implementation does not actually convert. Fix this.

OpenSSL::Buffering#puts and #print already correctly call #to_s.
IO#syswrite converts the argument with #to_s rather than #to_str.
Handle arrays and nested arrays in OpenSSL::Buffering#puts in a similar
fashion as IO#puts.
OpenSSL::Buffering already supports other character IO methods such
as #getc, #ungetc, or #readchar. Add the missing method.
@rhenium
rhenium force-pushed the ky/ssl-io-methods-updates branch from 919b916 to 01c3142 Compare September 2, 2026 11:20
Run assertions in test_pair.rb against a pair of real socket objects
to avoid accidentally introducing incompatible changes in SSLSocket or
OpenSSL::Buffering.
@rhenium
rhenium force-pushed the ky/ssl-io-methods-updates branch from 01c3142 to bc43561 Compare September 2, 2026 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant