It seems (maybe I am wrong and it could bring disaster ) that this could help:
# delimfound has meaning only after readuntil!
julia> delimfound(io, delim::Char) = eof(io) ? Char(take!(io)[end])==delim : true
# or you could do
julia> delim = ';' % UInt8;
julia> delimfound(io, delim::UInt8) = eof(io) ? take!(io)[end]==delim : true
julia> readuntil(io, delim) # this would be a little faster too
Idea: if you read to eof then take the buffered data and check if there was delimiter in the end.
It worked in my tests under julia1.0 with IOBuffer and IOStream, but I am not sure if it will work with your Type<:IO.
No. Did you miss that I wrote about IOStream too? Or about Type<:IO??
(BTW with IOBuffer it is easier you could do io.Ptr-=1 and then read last byte…)
But there is another problem wich make my workaround useless! For example for io = open("file") if file_size == n * cache_buffer_size (131072 in my case) there is eof(io) == false after reading last byte. And unfortunately cache is cleared by reading no bytes to get eof(io) == true so take!(io) return empty vector.
I am curious if there are other possibilities than fix readuntil to solve your problem.