From 8e2e403293287f9a7bf5341094be6206a745754f Mon Sep 17 00:00:00 2001
From: nick evans <nick@rubinick.dev>
Date: Wed, 2 Apr 2025 20:50:15 -0400
Subject: [PATCH 13/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Extract=20ResponseRe?=
=?UTF-8?q?ader=20from=20get=5Fresponse?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It's nice to extract a little bit of the complexity from the core
`Net::IMAP` class. But my primary motivation was so that I could
directly test this code quickly and in isolation from needing to
simulate a full IMAP connection.
.bundle/gems/net-imap-0.3.8/lib/net/imap.rb | 24 +++----------
.bundle/gems/net-imap-0.3.8/lib/net/imap/response_reader.rb | 38 +++++++++++++++++++++
2 files changed, 43 insertions(+), 19 deletions(-)
create mode 100644 .bundle/gems/net-imap-0.3.8/lib/net/imap/response_reader.rb
@@ -737,6 +737,8 @@ module Net
class IMAP < Protocol
VERSION = "0.3.8"
+ autoload :ResponseReader, File.expand_path("imap/response_reader", __dir__)
+
include MonitorMixin
if defined?(OpenSSL::SSL)
include OpenSSL
@@ -2074,6 +2076,7 @@ module Net
@idle_response_timeout = options[:idle_response_timeout] || 5
@parser = ResponseParser.new
@sock = tcp_socket(@host, @port)
+ @reader = ResponseReader.new(self, @sock)
begin
if options[:ssl]
start_tls_session(options[:ssl])
@@ -2225,30 +2228,12 @@ module Net
end
def get_response
- buff = String.new
- catch :eof do
- while true
- get_response_line(buff)
- break unless /\{(\d+)\}\r\n\z/n =~ buff
- get_response_literal(buff, $1.to_i)
- end
- end
+ buff = @reader.read_response_buffer
return nil if buff.length == 0
$stderr.print(buff.gsub(/^/n, "S: ")) if @@debug
@parser.parse(buff)
end
- def get_response_line(buff)
- line = @sock.gets(CRLF) or throw :eof
- buff << line
- end
-
- def get_response_literal(buff, literal_size)
- literal = String.new(capacity: literal_size)
- @sock.read(literal_size, literal) or throw :eof
- buff << literal
- end
-
#############################
def record_response(name, data)
@@ -2428,6 +2413,7 @@ module Net
context.verify_callback = VerifyCallbackProc
end
@sock = SSLSocket.new(@sock, context)
+ @reader = ResponseReader.new(self, @sock)
@sock.sync_close = true
@sock.hostname = @host if @sock.respond_to? :hostname=
ssl_socket_connect(@sock, @open_timeout)
new file mode 100644
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Net
+ class IMAP
+ # See https://www.rfc-editor.org/rfc/rfc9051#section-2.2.2
+ class ResponseReader # :nodoc:
+ attr_reader :client
+
+ def initialize(client, sock)
+ @client, @sock = client, sock
+ end
+
+ def read_response_buffer
+ buff = String.new
+ catch :eof do
+ while true
+ read_line(buff)
+ break unless /\{(\d+)\}\r\n\z/n =~ buff
+ read_literal(buff, $1.to_i)
+ end
+ end
+ buff
+ end
+
+ private
+
+ def read_line(buff)
+ buff << (@sock.gets(CRLF) or throw :eof)
+ end
+
+ def read_literal(buff, literal_size)
+ literal = String.new(capacity: literal_size)
+ buff << (@sock.read(literal_size, literal) or throw :eof)
+ end
+
+ end
+ end
+end
--
2.27.0