From b98ef6dbb5d7e0fee7a9f73605a4718f2f4f703d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 10 Oct 2024 12:23:29 -0400 Subject: [PATCH] stream: fix reading LibuvStream into array Adds a new abstraction `take!(::Array{T,N}, ::Array{T,N})` for doing an efficient `copyto!` equivalent. Previously it was assumed that `compact` did this automatically, which wasn't a great assumption. Fixes #56078 --- base/array.jl | 11 +++++++++++ base/io.jl | 4 ++++ base/stream.jl | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index 5b3e6cc3984798..5d34cbbaf8bebd 100644 --- a/base/array.jl +++ b/base/array.jl @@ -351,6 +351,17 @@ copy return $(Expr(:new, :(typeof(a)), :(memoryref(newmem)), :(a.size))) end +# a mutating version of copyto! that results in dst aliasing src afterwards +function take!(dst::Array{T,N}, src::Array{T,N}) where {T,N} + if getfield(dst, :ref) !== getfield(src, :ref) + setfield!(dst, :ref, getfield(src, :ref)) + end + if getfield(dst, :size) !== getfield(src, :size) + setfield!(dst, :size, getfield(src, :size)) + end + return dst +end + ## Constructors ## similar(a::Array{T,1}) where {T} = Vector{T}(undef, size(a,1)) diff --git a/base/io.jl b/base/io.jl index 83a215d6359fce..025ed037438d06 100644 --- a/base/io.jl +++ b/base/io.jl @@ -1541,3 +1541,7 @@ function countlines(io::IO; eol::AbstractChar='\n') end countlines(f::AbstractString; eol::AbstractChar = '\n') = open(io->countlines(io, eol = eol), f)::Int + +# double mutating version of take! +take!(b::Vector{UInt8}, io::IO) = take!(b, take!(io)) +_unsafe_take!(b::Vector{UInt8}, io::IO) = take!(b, _unsafe_take!(io)) diff --git a/base/stream.jl b/base/stream.jl index 93aeead79eb9ce..8e4de3b975151c 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -944,7 +944,7 @@ function readbytes!(s::LibuvStream, a::Vector{UInt8}, nb::Int) finally s.buffer = sbuf end - compact(newbuf) + _unsafe_take!(a, newbuf) end iolock_end() return nread