-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a "prefill" method to IO::Buffered with read buffering #15075
Comments
Maybe a I like the generic prefill method, but looking at |
Agree! |
This seems like it could be useful. However I'm wondering about the behaviour outside the happy path. For example, what happens on EOF? I suppose the result is trimmed down to the size of available data? But then we must make sure to not assume This filled peek also needs a memmove on the peek buffer. I don't see any immediate downside of that except that it can have a performance effect. But that should be neglectable because peek size is usually low. Another positive effect I can think of is that this could perhaps allow us to simplify some algorithms. |
Currently I've done https://github.com/cloudamqp/lavinmq/blob/ba4adbddaa76dfadfe8310df0b42e9d1c0d52e7c/src/stdlib/io_buffered.cr in LavinMQ. Maybe I'm missing a case or two, and I know it's only used for sockets. |
Yeah, I think there's a bug in your code: And it does not handle the case where # This should fill the buffer and consume all but the last byte
io.read(Bytes.new(io.buffer_size - 1))
# Now we want to read one more byte than the buffer's capacity
io.peek(2) In order to fix this, we need to always move the contents of |
Hm. My intention was to try to fill the entire buffer, but at least
I'm only reading while What i want |
I have these specs that maybe shows what I want the method to do. |
Hm, seems like misread the code, sorry. So So I still think we need to move |
Yeah, i recreate |
I think I understand what you mean now, yes. |
I was thinking the algorithm should look something like this (untested): if @in_buffer_rem.size < size
# We need to read more into the buffer
in_buffer = in_buffer()
# 1. Move leftover data to the front of the buffer so we have maximum capacity to fill
@in_buffer_rem.copy_to(in_buffer, @in_buffer_rem.size)
# 2. Fill the buffer up to at least size
while @in_buffer_rem.size < size
bytes_read = unbuffered_read(in_buffer + @in_buffer_rem.size).to_i
break if bytes_read.zero?
@in_buffer_rem = Slice.new(@in_buffer, @in_buffer_rem.size + bytes_read)
end
end
@in_buffer_rem[0, size] |
Exactly. I just did a spec to verify that. |
Currently I have https://github.com/cloudamqp/lavinmq/pull/803/files I think it make sense to raise something if we can't read |
I'm not too happy about raising. It's costly and not alway necessary. |
I hear ya! |
Feature Request
I haven't found a way to "prefill " a
IO::Buffered
withread_buffering? == true
. I want to fill it's buffer with at leastn
bytes (n <= buffer_size
).A use case is that I'd like to peek into the buffer to see some bytes to autodetect what protocol a socket client is using. A
peek
call will trigger a fill, but if not enough data is read I have no way of telling the IO to read more data.I'd like to do something like
The text was updated successfully, but these errors were encountered: