@@ -523,6 +523,9 @@ abstract class IO
523523 # slice # => Bytes[49, 50, 51, 52, 53]
524524 # io.read_fully(slice) # raises IO::EOFError
525525 # ```
526+ #
527+ # `#read_greedy` also tries to fill the entire buffer if possible,
528+ # but still allows the partially filled slice to be used if an early EOF was reached.
526529 def read_fully (slice : Bytes ) : Int32
527530 read_fully?(slice) || raise(EOFError .new)
528531 end
@@ -538,11 +541,34 @@ abstract class IO
538541 # slice # => Bytes[49, 50, 51, 52, 53]
539542 # io.read_fully?(slice) # => nil
540543 # ```
544+ #
545+ # `#read_greedy` also tries to fill the entire buffer if possible,
546+ # but still allows the partially filled slice to be used if an early EOF was reached.
541547 def read_fully ?(slice : Bytes ) : Int32 ?
548+ count = read_greedy(slice)
549+ return nil if count != slice.size
550+ count
551+ end
552+
553+ # Similar to `#read`, but with the additional guarantee that either
554+ # the buffer will be entirely filled or the EOF will be reached while trying.
555+ #
556+ # Calling this method may result in multiple calls to `#read` if necessary.
557+ #
558+ # ```
559+ # io = IO::Memory.new "123451234"
560+ # slice = Bytes.new(5)
561+ # io.read_greedy(slice) # => 5
562+ # slice # => Bytes[49, 50, 51, 52, 53]
563+ # io.read_greedy(slice) # => 4
564+ # ```
565+ #
566+ # `#read_fully` and `#read_fully?` also try to fill the entire buffer but error on unexpected EOF.
567+ def read_greedy (slice : Bytes ) : Int32
542568 count = slice.size
543569 while slice.size > 0
544- read_bytes = read slice
545- return nil if read_bytes == 0
570+ read_bytes = read( slice)
571+ return count &- slice.size if read_bytes == 0
546572 slice += read_bytes
547573 end
548574 count
0 commit comments