-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Feature Request
IO#read currently makes very few assumptions about the amount of data that must be read (only that 0 bytes returned = EOF).
This can be cumbersome when writing methods which process IO data.
Because of this, lots of code currently makes the assumption that IO#read fills the entire buffer if enough data is available (ex. #14604).
The only methods which currently allow reading greedily (#read_fully, #read_fully?) do not return the amount of bytes read if the buffer was not filled entirely, causing the remaining bytes to be lost if the IO does not implement #pos.
Therefore, I think it would be useful to add a separate method with this behaviour:
# Similar to `#read`, but with the additional guarantee that either
# the buffer will be entirely filled or the EOF will be reached while trying.
#
# Calling this method may result in multiple read calls if necessary.
def read_greedy(slice : Bytes) : Int32
count = slice.size
while slice.size > 0
read_bytes = read(slice)
return count &- slice.size if read_bytes == 0
slice += read_bytes
end
count
endAdding this as a separate method allows many IOs which already have this behavior implicitly (ex. IO::Memory) to implement it more efficiently while ensuring correctness for IOs which do not have this behavior.
Additionally, as an opposite counterpart, it may be useful to add a method (IO#read_lazy ?) for reading from an IO lazily (ex. non-blocking read from STDIN which simply returns 0 if there was no user input without concurrency).