diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0f2018a..0243b4c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,6 +16,7 @@ jobs: fail-fast: false matrix: version: + - '1.10' - '1' - 'pre' os: diff --git a/src/reader.jl b/src/reader.jl index 7ac82c2..8a62bf3 100644 --- a/src/reader.jl +++ b/src/reader.jl @@ -5,19 +5,27 @@ function unsafe_crc32(p::Ptr{UInt8}, nb::UInt, crc::UInt32)::UInt32 ) end -const ByteArray = Union{ - Base.CodeUnits{UInt8, String}, - Vector{UInt8}, - Base.FastContiguousSubArray{UInt8,1,Base.CodeUnits{UInt8,String}}, - Base.FastContiguousSubArray{UInt8,1,Vector{UInt8}} -} +if VERSION ≥ v"1.11" + const ByteArray = Union{ + Base.CodeUnits{UInt8, String}, + Vector{UInt8}, + Base.FastContiguousSubArray{UInt8,1,Base.CodeUnits{UInt8,String}}, + Base.FastContiguousSubArray{UInt8,1,Vector{UInt8}}, + Memory{UInt8}, + Base.FastContiguousSubArray{UInt8,1,Memory{UInt8}} + } +else + const ByteArray = Union{ + Base.CodeUnits{UInt8, String}, + Vector{UInt8}, + Base.FastContiguousSubArray{UInt8,1,Base.CodeUnits{UInt8,String}}, + Base.FastContiguousSubArray{UInt8,1,Vector{UInt8}} + } +end # version of String(v::AbstractVector{UInt8}) that works consistently. function bytes2string(v::AbstractVector{UInt8})::String - String(v) -end -function bytes2string(v::Vector{UInt8})::String - GC.@preserve v unsafe_string(pointer(v), length(v)) + String(view(v,:)) end """ @@ -32,7 +40,17 @@ function zip_crc32(data::ByteArray, crc::UInt32=UInt32(0))::UInt32 end function zip_crc32(data::AbstractVector{UInt8}, crc::UInt32=UInt32(0))::UInt32 - zip_crc32(collect(data), crc) + start::Int64 = firstindex(data) + n::Int64 = length(data) + offset::Int64 = 0 + buf = Vector{UInt8}(undef, min(n, Int64(24576))) + while offset < n + nb = min(n-offset, Int64(24576)) + copyto!(buf, 1, data, offset + start, nb) + crc = zip_crc32(view(buf, 1:nb), crc) + offset += nb + end + crc end @inline readle(io::IO, ::Type{UInt64}) = UInt64(readle(io, UInt32)) | UInt64(readle(io, UInt32))<<32 diff --git a/test/Project.toml b/test/Project.toml index 9c9a47b..24c6318 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,3 +1,6 @@ +[sources] +ZipArchives = {path = ".."} + [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" diff --git a/test/test_bytes2string.jl b/test/test_bytes2string.jl index 6cbb8ed..45977e1 100644 --- a/test/test_bytes2string.jl +++ b/test/test_bytes2string.jl @@ -56,4 +56,24 @@ using OffsetArrays: Origin @test a == [0x62,0x62,0x63] @test c == [0x62,0x62,0x63] @test s == "abc" + + if VERSION ≥ v"1.11" + a = Base.Memory{UInt8}(undef, 3) + a .= [0x41,0x42,0x43] + s = ZipArchives.bytes2string(a) + @test s == "ABC" + @test a == [0x41,0x42,0x43] + a[1] = 0x43 + @test s == "ABC" + @test a == [0x43,0x42,0x43] + + a = view(Base.Memory{UInt8}(undef, 3), 1:3) + a .= [0x41,0x42,0x43] + s = ZipArchives.bytes2string(a) + @test s == "ABC" + @test a == [0x41,0x42,0x43] + a[1] = 0x43 + @test s == "ABC" + @test a == [0x43,0x42,0x43] + end end \ No newline at end of file diff --git a/test/test_reader.jl b/test/test_reader.jl index 9e40321..080d10a 100644 --- a/test/test_reader.jl +++ b/test/test_reader.jl @@ -306,6 +306,25 @@ end @test zip_readentry(r, 1) == codeunits("KYDtLOxn") end +if VERSION ≥ v"1.11" + @testset "reading from memory" begin + io = IOBuffer() + ZipWriter(io) do w + zip_writefile(w, "foo.txt", codeunits("KYDtLOxn")) + end + data = take!(io) + n = length(data) + a = Base.Memory{UInt8}(undef, n) + a .= data + r = ZipReader(a) + @test zip_names(r) == ["foo.txt"] + @test zip_readentry(r, 1) == codeunits("KYDtLOxn") + r = ZipReader(view(a, 1:length(a))) + @test zip_names(r) == ["foo.txt"] + @test zip_readentry(r, 1) == codeunits("KYDtLOxn") + end +end + function rewrite_zip(old::AbstractString, new::AbstractString) d = mmap(old) try diff --git a/test/test_writer.jl b/test/test_writer.jl index 4702d3b..8fea46e 100644 --- a/test/test_writer.jl +++ b/test/test_writer.jl @@ -439,4 +439,32 @@ end end r = ZipReader(take!(out)) @test zip_readentry(r, "data.txt") == 0x01:0x0f -end \ No newline at end of file +end + +if VERSION ≥ v"1.11" + @testset "zip_writefile on memory" begin + data = [0x41,0x42,0x43] + a = Base.Memory{UInt8}(undef, 3) + a .= data + @test zip_crc32(data) == zip_crc32(a) + out = IOBuffer() + ZipWriter(out) do w + zip_writefile(w, "data.txt", a) + end + r = ZipReader(take!(out)) + @test zip_readentry(r, "data.txt") == data + end + @testset "zip_writefile on view of memory" begin + data = [0x41,0x42,0x43] + m = Base.Memory{UInt8}(undef, 3) + m .= data + a = view(m, :) + @test zip_crc32(data) == zip_crc32(a) + out = IOBuffer() + ZipWriter(out) do w + zip_writefile(w, "data.txt", a) + end + r = ZipReader(take!(out)) + @test zip_readentry(r, "data.txt") == data + end +end