zip_kit 6.3.0 → 6.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/CHANGELOG.md +4 -0
- data/IMPLEMENTATION_DETAILS.md +9 -35
- data/README.md +20 -11
- data/RUBYZIP_DIFFERENCES.md +1 -4
- data/lib/zip_kit/block_deflate.rb +8 -8
- data/lib/zip_kit/file_reader.rb +17 -17
- data/lib/zip_kit/rails_streaming.rb +1 -1
- data/lib/zip_kit/railtie.rb +3 -1
- data/lib/zip_kit/remote_io.rb +2 -2
- data/lib/zip_kit/size_estimator.rb +4 -4
- data/lib/zip_kit/stream_crc32.rb +5 -5
- data/lib/zip_kit/version.rb +1 -1
- data/lib/zip_kit/write_shovel.rb +1 -1
- data/lib/zip_kit/zip_writer.rb +20 -20
- data/rbi/zip_kit.rbi +62 -62
- metadata +3 -6
- data/.document +0 -5
- data/.rspec +0 -1
- data/bench/buffered_crc32_bench.rb +0 -109
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 442833a965d373fd56e8d085164f536e17560ed4a74e11aab5befc61946de1bc
|
4
|
+
data.tar.gz: 6c470314702d643b8f5b55fb3a328ab62cecfe1982587df9b8179fd84bf9013e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8532b5faf979cc98ba0f1e05dff6adf3e6748466553446397c3f7f706fe663182f8fab47a973e3e911b2457eb0622579a62d7b35c1fe18644b7ea05541d7e316
|
7
|
+
data.tar.gz: 377ef88938f5ec86ea6cd2e15c6857eac9ff2ffc25bb629cf2a0d0ba774a823013e4b4061d1a5392dc4b88e8cbd3d022a1f90e41d1cb68ad72c5e9d42f3c51cd
|
data/.github/workflows/ci.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 6.3.1
|
2
|
+
|
3
|
+
* Include `RailsStreaming` in a Rails loader callback, so that ActionController does not need to be in the namespace.
|
4
|
+
|
1
5
|
## 6.3.0
|
2
6
|
|
3
7
|
* Include `RailsStreaming` automatically via a Railtie. It is not really necessary to force people to manage it manually.
|
data/IMPLEMENTATION_DETAILS.md
CHANGED
@@ -5,6 +5,7 @@ The ZipKit streaming implementation is designed around the following requirement
|
|
5
5
|
* Only ahead-writes (no IO seek or rewind)
|
6
6
|
* Automatic switching to Zip64 as the files get written (no IO seeks), but not requiring Zip64 support if the archive can do without
|
7
7
|
* Make use of the fact that CRC32 checksums and the sizes of the files (compressed _and_ uncompressed) are known upfront
|
8
|
+
* Make it possible to output "sparse" ZIP archives (manifests that can be resolved into a ZIP via edge includes)
|
8
9
|
|
9
10
|
It strives to be compatible with the following unzip programs _at the minimum:_
|
10
11
|
|
@@ -14,9 +15,6 @@ It strives to be compatible with the following unzip programs _at the minimum:_
|
|
14
15
|
* Windows 7 - 7Zip 9.20
|
15
16
|
|
16
17
|
Below is the list of _specific_ decisions taken when writing the implementation, with an explanation for each.
|
17
|
-
We specifically _omit_ a number of things that we could do, but that are not necessary to satisfy our objectives.
|
18
|
-
The omissions are _intentional_ since we do not want to have things of which we _assume_ they work, or have things
|
19
|
-
that work only for one obscure unarchiver in one obscure case (like WinRAR with chinese filenames).
|
20
18
|
|
21
19
|
## Data descriptors (postfix CRC32/file sizes)
|
22
20
|
|
@@ -53,38 +51,14 @@ field, any other extra fields should come after.
|
|
53
51
|
|
54
52
|
If a diacritic-containing character (such as å) does fit into the DOS-437
|
55
53
|
codepage, it should be encodable as such. This would, in theory, let older Windows tools
|
56
|
-
decode the filename correctly. However, this
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
it will (very rightfully) ask us how we should decode each filename that does not have the EFS bit,
|
65
|
-
but does contain something non-ASCII-decodable. This is horrible UX for users.
|
66
|
-
|
67
|
-
So, basically, we have 2 choices, for filenames containing diacritics (for bona-fide UTF-8 you do not
|
68
|
-
even get those choices, you _have_ to use UTF-8):
|
69
|
-
|
70
|
-
* Make life easier for Windows users by setting stuff to DOS, not care about the standard _and_ make
|
71
|
-
most of Mac users upset
|
72
|
-
* Make life easy for Mac users and conform to the standard, and tell Windows users to get a _decent_
|
73
|
-
ZIP unarchiving tool.
|
74
|
-
|
75
|
-
We are going with option 2, and this is well-thought-out. Trust me. If you want the crazytown
|
76
|
-
filename encoding scheme that is described here http://stackoverflow.com/questions/13261347
|
77
|
-
you can try this:
|
78
|
-
|
79
|
-
[Encoding::CP437, Encoding::ISO_8859_1, Encoding::UTF_8]
|
80
|
-
|
81
|
-
While this could work, we found it to be broken in practice as the decoding of the filename
|
82
|
-
also depends on the system locale.
|
83
|
-
|
84
|
-
Additionally, the tests with the unarchivers we _do_ support have shown that including the InfoZIP
|
85
|
-
extra field does not actually help any of them recognize the file name correctly. And the use of
|
86
|
-
those fields for the UTF-8 filename, per spec, tells us we should not set the EFS bit - which ruins
|
87
|
-
the unarchiving for all other solutions. As any other, this decision may be changed in the future.
|
54
|
+
decode the filename correctly. However, this only works under the following circumstances:
|
55
|
+
|
56
|
+
* All the filenames in the archive are within the same "super-ASCII" encoding
|
57
|
+
* The Windows locale on the computer opening the archive is set to the same locale as the filename in the archive
|
58
|
+
|
59
|
+
A better approach is to use the EFS flag, which we enable when a filename does not encode cleanly
|
60
|
+
into base ASCII. The extended filename extra field did not work well for us - and it does not
|
61
|
+
combine correctly with the EFS flag.
|
88
62
|
|
89
63
|
There are some interesting notes about the Info-ZIP/EFS combination here
|
90
64
|
https://commons.apache.org/proper/commons-compress/zip.html
|
data/README.md
CHANGED
@@ -5,16 +5,19 @@
|
|
5
5
|
|
6
6
|
Allows streaming, non-rewinding ZIP file output from Ruby.
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
to develop zip_tricks and for sharing it with the community.
|
8
|
+
> [!IMPORTANT]
|
9
|
+
> `zip_kit` is a successor to and continuation of [zip_tricks.](https://github.com/WeTransfer/zip_tricks)
|
10
|
+
> I am grateful to WeTransfer for allowing me to develop zip_tricks and for sharing it with the community.
|
11
11
|
|
12
12
|
Allows you to write a ZIP archive out to a `File`, `Socket`, `String` or `Array` without having to rewind it at any
|
13
13
|
point. Usable for creating very large ZIP archives for immediate sending out to clients, or for writing
|
14
14
|
large ZIP archives without memory inflation.
|
15
15
|
|
16
|
-
The
|
17
|
-
|
16
|
+
The gem handled all the zipping needs for WeTransfer for half a decade, with hundreds of millions
|
17
|
+
of correct ZIP files generated. It is compatible with most end-user applications for opening archives.
|
18
|
+
|
19
|
+
The files output with zip_kit will be valid [OCF containers](https://www.w3.org/TR/epub-33/#sec-container-zip),
|
20
|
+
the library can be used to generate JAR files, EPUBs, OpenOffice/Office documents etc.
|
18
21
|
|
19
22
|
## How does it work? How is it different from Rubyzip?
|
20
23
|
|
@@ -22,6 +25,13 @@ Check out [the implementation details](IMPLEMENTATION_DETAILS.md) on the design
|
|
22
25
|
we have a separate [reference](RUBYZIP_DIFFERENCES.md) on why you might want to use ZipKit over
|
23
26
|
Rubyzip and vice versa.
|
24
27
|
|
28
|
+
## Migrating from zip_tricks
|
29
|
+
|
30
|
+
If you want to migrate your code from zip_tricks to zip_kit, all you need to do is a blanket replacement in your code.
|
31
|
+
Swap out the `ZipTricks` constant for `ZipKit` and you should be in business. All of the API available in ZipTricks 5.x
|
32
|
+
still works as of ZipKit 6.x and will stay working. If something in your project still depends on zip_tricks you can use
|
33
|
+
both gems inside of the same "apex" project - there will be no conflicts.
|
34
|
+
|
25
35
|
## Requirements
|
26
36
|
|
27
37
|
Ruby 2.6+ syntax support is required, as well as a a working zlib (all available to jRuby as well).
|
@@ -60,9 +70,8 @@ If you want some more conveniences you can also use [zipline](https://github.com
|
|
60
70
|
will automatically process and stream attachments (Carrierwave, Shrine, ActiveStorage) and remote objects
|
61
71
|
via HTTP.
|
62
72
|
|
63
|
-
`
|
64
|
-
and will stream without it.
|
65
|
-
together with `Live` just fine if you need to.
|
73
|
+
`zip_kit_stream` does *not* require [ActionController::Live](https://api.rubyonrails.org/classes/ActionController/Live.html)
|
74
|
+
and will stream without it. It will work inside `Live` controllers just fine though.
|
66
75
|
|
67
76
|
## Writing into streaming destinations
|
68
77
|
|
@@ -128,10 +137,10 @@ output direct to STDOUT (so that you can run `$ ruby archive.rb > file.zip` in y
|
|
128
137
|
|
129
138
|
```ruby
|
130
139
|
ZipKit::Streamer.open($stdout) do |zip|
|
131
|
-
zip.write_file('mov.mp4
|
140
|
+
zip.write_file('mov.mp4') do |sink| # Will use "stored" mode
|
132
141
|
File.open('mov.mp4', 'rb'){|source| IO.copy_stream(source, sink) }
|
133
142
|
end
|
134
|
-
zip.write_file('long-novel.txt') do |sink|
|
143
|
+
zip.write_file('long-novel.txt') do |sink| # Will use "deflated" mode
|
135
144
|
File.open('novel.txt', 'rb'){|source| IO.copy_stream(source, sink) }
|
136
145
|
end
|
137
146
|
end
|
@@ -166,7 +175,7 @@ end
|
|
166
175
|
Sending a file with data descriptors is not always desirable - you don't really know how large your ZIP is going to be.
|
167
176
|
If you want to present your users with proper download progress, you would need to set a `Content-Length` header - and
|
168
177
|
know ahead of time how large your download is going to be. This can be done with ZipKit, provided you know how large
|
169
|
-
the compressed versions of your file are going to be. Use the
|
178
|
+
the compressed versions of your file are going to be. Use the `ZipKit::SizeEstimator` to do the pre-calculation - it
|
170
179
|
is not going to produce any large amounts of output, and will give you a to-the-byte value for your future archive:
|
171
180
|
|
172
181
|
```ruby
|
data/RUBYZIP_DIFFERENCES.md
CHANGED
@@ -16,10 +16,6 @@ differences in supported features which may be important for you when choosing.
|
|
16
16
|
and Zip64, and is economical enough to enable "remote uncapping" where pieces of a ZIP file get read over HTTP to reconstruct
|
17
17
|
the archive structure. Actual reading can then be done on a per-entry basis. Rubyzip reads entry data from local entries, which
|
18
18
|
is error prone and much less economical than using the central directory
|
19
|
-
* ZipKit deliberately _does not_ allow you to crawl directories to add to an archive, as this has been used for security exploits
|
20
|
-
in Rubyzip.
|
21
|
-
* ZipKit deliberately _does not_ allow you to extract a ZIP archive directly to the filesystem, as this has been used for security
|
22
|
-
exploits in Rubyzip.
|
23
19
|
* When writing, ZipKit applies careful buffering to speed up CRC32 calculations. Rubyzip combines CRC32 values at every write, which
|
24
20
|
can be slow if there are many small writes.
|
25
21
|
* ZipKit comes with a Rails helper and a Rack-compatible response body for facilitating streaming. Rubyzip has no Rails integration
|
@@ -29,6 +25,7 @@ differences in supported features which may be important for you when choosing.
|
|
29
25
|
* ZipKit requires components using autoloading, which means that your application will likely boot faster as you will almost never
|
30
26
|
need all of the features in one codebase. Rubyzip requires its components eagerly.
|
31
27
|
* ZipKit comes with exhaustive YARD documentation and `.rbi` typedefs for [Sorbet/Tapioca](https://sorbet.org/blog/2022/07/27/srb-tapioca)
|
28
|
+
* ZipKit allows you to compose "sparse" ZIP files where the contents of the files inside the archive comes from an external source, and does not have to be passed through the library (or be turned into Ruby strings), which enables interesting use cases such as download proxies with random access and resume.
|
32
29
|
|
33
30
|
## What Rubyzip supports and ZipKit does not
|
34
31
|
|
@@ -55,7 +55,7 @@ class ZipKit::BlockDeflate
|
|
55
55
|
# `output_io` can also be a {ZipKit::Streamer} to expedite ops.
|
56
56
|
#
|
57
57
|
# @param output_io [IO] the stream to write to (should respond to `:<<`)
|
58
|
-
# @return [
|
58
|
+
# @return [Integer] number of bytes written to `output_io`
|
59
59
|
def self.write_terminator(output_io)
|
60
60
|
output_io << END_MARKER
|
61
61
|
END_MARKER.bytesize
|
@@ -65,7 +65,7 @@ class ZipKit::BlockDeflate
|
|
65
65
|
# The returned string can be spliced into another deflate stream.
|
66
66
|
#
|
67
67
|
# @param bytes [String] Bytes to compress
|
68
|
-
# @param level [
|
68
|
+
# @param level [Integer] Zlib compression level (defaults to `Zlib::DEFAULT_COMPRESSION`)
|
69
69
|
# @return [String] compressed bytes
|
70
70
|
def self.deflate_chunk(bytes, level: Zlib::DEFAULT_COMPRESSION)
|
71
71
|
raise "Invalid Zlib compression level #{level}" unless VALID_COMPRESSIONS.include?(level)
|
@@ -90,9 +90,9 @@ class ZipKit::BlockDeflate
|
|
90
90
|
#
|
91
91
|
# @param input_io [IO] the stream to read from (should respond to `:read`)
|
92
92
|
# @param output_io [IO] the stream to write to (should respond to `:<<`)
|
93
|
-
# @param level [
|
94
|
-
# @param block_size [
|
95
|
-
# @return [
|
93
|
+
# @param level [Integer] Zlib compression level (defaults to `Zlib::DEFAULT_COMPRESSION`)
|
94
|
+
# @param block_size [Integer] The block size to use (defaults to `DEFAULT_BLOCKSIZE`)
|
95
|
+
# @return [Integer] number of bytes written to `output_io`
|
96
96
|
def self.deflate_in_blocks_and_terminate(input_io,
|
97
97
|
output_io,
|
98
98
|
level: Zlib::DEFAULT_COMPRESSION,
|
@@ -110,9 +110,9 @@ class ZipKit::BlockDeflate
|
|
110
110
|
#
|
111
111
|
# @param input_io [IO] the stream to read from (should respond to `:read`)
|
112
112
|
# @param output_io [IO] the stream to write to (should respond to `:<<`)
|
113
|
-
# @param level [
|
114
|
-
# @param block_size [
|
115
|
-
# @return [
|
113
|
+
# @param level [Integer] Zlib compression level (defaults to `Zlib::DEFAULT_COMPRESSION`)
|
114
|
+
# @param block_size [Integer] The block size to use (defaults to `DEFAULT_BLOCKSIZE`)
|
115
|
+
# @return [Integer] number of bytes written to `output_io`
|
116
116
|
def self.deflate_in_blocks(input_io,
|
117
117
|
output_io,
|
118
118
|
level: Zlib::DEFAULT_COMPRESSION,
|
data/lib/zip_kit/file_reader.rb
CHANGED
@@ -86,46 +86,46 @@ class ZipKit::FileReader
|
|
86
86
|
# the Entry object used in Streamer for ZIP writing, since during writing more
|
87
87
|
# data can be kept in memory for immediate use.
|
88
88
|
class ZipEntry
|
89
|
-
# @return [
|
89
|
+
# @return [Integer] bit-packed version signature of the program that made the archive
|
90
90
|
attr_accessor :made_by
|
91
91
|
|
92
|
-
# @return [
|
92
|
+
# @return [Integer] ZIP version support needed to extract this file
|
93
93
|
attr_accessor :version_needed_to_extract
|
94
94
|
|
95
|
-
# @return [
|
95
|
+
# @return [Integer] bit-packed general purpose flags
|
96
96
|
attr_accessor :gp_flags
|
97
97
|
|
98
|
-
# @return [
|
98
|
+
# @return [Integer] Storage mode (0 for stored, 8 for deflate)
|
99
99
|
attr_accessor :storage_mode
|
100
100
|
|
101
|
-
# @return [
|
101
|
+
# @return [Integer] the bit-packed DOS time
|
102
102
|
attr_accessor :dos_time
|
103
103
|
|
104
|
-
# @return [
|
104
|
+
# @return [Integer] the bit-packed DOS date
|
105
105
|
attr_accessor :dos_date
|
106
106
|
|
107
|
-
# @return [
|
107
|
+
# @return [Integer] the CRC32 checksum of this file
|
108
108
|
attr_accessor :crc32
|
109
109
|
|
110
|
-
# @return [
|
110
|
+
# @return [Integer] size of compressed file data in the ZIP
|
111
111
|
attr_accessor :compressed_size
|
112
112
|
|
113
|
-
# @return [
|
113
|
+
# @return [Integer] size of the file once uncompressed
|
114
114
|
attr_accessor :uncompressed_size
|
115
115
|
|
116
116
|
# @return [String] the filename
|
117
117
|
attr_accessor :filename
|
118
118
|
|
119
|
-
# @return [
|
119
|
+
# @return [Integer] disk number where this file starts
|
120
120
|
attr_accessor :disk_number_start
|
121
121
|
|
122
|
-
# @return [
|
122
|
+
# @return [Integer] internal attributes of the file
|
123
123
|
attr_accessor :internal_attrs
|
124
124
|
|
125
|
-
# @return [
|
125
|
+
# @return [Integer] external attributes of the file
|
126
126
|
attr_accessor :external_attrs
|
127
127
|
|
128
|
-
# @return [
|
128
|
+
# @return [Integer] at what offset the local file header starts
|
129
129
|
# in your original IO object
|
130
130
|
attr_accessor :local_file_header_offset
|
131
131
|
|
@@ -151,7 +151,7 @@ class ZipKit::FileReader
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
# @return [
|
154
|
+
# @return [Integer] at what offset you should start reading
|
155
155
|
# for the compressed data in your original IO object
|
156
156
|
def compressed_data_offset
|
157
157
|
@compressed_data_offset || raise(LocalHeaderPending)
|
@@ -298,7 +298,7 @@ class ZipKit::FileReader
|
|
298
298
|
# this offset to get the data).
|
299
299
|
#
|
300
300
|
# @param io[#read] an IO-ish object the ZIP file can be read from
|
301
|
-
# @return [Array<ZipEntry,
|
301
|
+
# @return [Array<ZipEntry, Integer>] the parsed local header entry and
|
302
302
|
# the compressed data offset
|
303
303
|
def read_local_file_header(io:)
|
304
304
|
local_file_header_offset = io.tell
|
@@ -365,8 +365,8 @@ class ZipKit::FileReader
|
|
365
365
|
# (read starting at this offset to get the data).
|
366
366
|
#
|
367
367
|
# @param io[#seek, #read] an IO-ish object the ZIP file can be read from
|
368
|
-
# @param local_file_header_offset[
|
369
|
-
# local file header is supposed to begin @return [
|
368
|
+
# @param local_file_header_offset[Integer] absolute offset (0-based) where the
|
369
|
+
# local file header is supposed to begin @return [Integer] absolute offset
|
370
370
|
# (0-based) of where the compressed data begins for this file within the ZIP
|
371
371
|
def get_compressed_data_offset(io:, local_file_header_offset:)
|
372
372
|
seek(io, local_file_header_offset)
|
@@ -24,7 +24,7 @@ module ZipKit::RailsStreaming
|
|
24
24
|
# @param use_chunked_transfer_encoding[Boolean] whether to forcibly encode output as chunked. Normally you should not need this.
|
25
25
|
# @param output_enumerator_options[Hash] options that will be passed to the OutputEnumerator - these include
|
26
26
|
# options for the Streamer. See {ZipKit::OutputEnumerator#initialize} for the full list of options.
|
27
|
-
# @yieldparam [ZipKit::Streamer]
|
27
|
+
# @yieldparam zip[ZipKit::Streamer] the {ZipKit::Streamer} that can be written to
|
28
28
|
# @return [Boolean] always returns true
|
29
29
|
def zip_kit_stream(filename: "download.zip", type: "application/zip", use_chunked_transfer_encoding: false, **output_enumerator_options, &zip_streaming_blk)
|
30
30
|
# We want some common headers for file sending. Rails will also set
|
data/lib/zip_kit/railtie.rb
CHANGED
data/lib/zip_kit/remote_io.rb
CHANGED
@@ -40,7 +40,7 @@ class ZipKit::RemoteIO
|
|
40
40
|
# so if you are at offset 0 in the IO of size 10, doing a `read(20)`
|
41
41
|
# will only return you 10 bytes of result, and not raise any exceptions.
|
42
42
|
#
|
43
|
-
# @param n_bytes[
|
43
|
+
# @param n_bytes[Integer, nil] how many bytes to read, or `nil` to read all the way to the end
|
44
44
|
# @return [String] the read bytes
|
45
45
|
def read(n_bytes = nil)
|
46
46
|
# If the resource is empty there is nothing to read
|
@@ -62,7 +62,7 @@ class ZipKit::RemoteIO
|
|
62
62
|
|
63
63
|
# Returns the current pointer position within the IO
|
64
64
|
#
|
65
|
-
# @return [
|
65
|
+
# @return [Integer]
|
66
66
|
def tell
|
67
67
|
@pos
|
68
68
|
end
|
@@ -24,7 +24,7 @@ class ZipKit::SizeEstimator
|
|
24
24
|
#
|
25
25
|
# @param kwargs_for_streamer_new Any options to pass to Streamer, see {Streamer#initialize}
|
26
26
|
# @return [Integer] the size of the resulting archive, in bytes
|
27
|
-
# @yieldparam [SizeEstimator] the estimator
|
27
|
+
# @yieldparam estimator[SizeEstimator] the estimator
|
28
28
|
def self.estimate(**kwargs_for_streamer_new)
|
29
29
|
streamer = ZipKit::Streamer.new(ZipKit::NullWriter, **kwargs_for_streamer_new)
|
30
30
|
estimator = new(streamer)
|
@@ -35,7 +35,7 @@ class ZipKit::SizeEstimator
|
|
35
35
|
# Add a fake entry to the archive, to see how big it is going to be in the end.
|
36
36
|
#
|
37
37
|
# @param filename [String] the name of the file (filenames are variable-width in the ZIP)
|
38
|
-
# @param size [
|
38
|
+
# @param size [Integer] size of the uncompressed entry
|
39
39
|
# @param use_data_descriptor[Boolean] whether the entry uses a postfix
|
40
40
|
# data descriptor to specify size
|
41
41
|
# @return self
|
@@ -54,8 +54,8 @@ class ZipKit::SizeEstimator
|
|
54
54
|
# Add a fake entry to the archive, to see how big it is going to be in the end.
|
55
55
|
#
|
56
56
|
# @param filename [String] the name of the file (filenames are variable-width in the ZIP)
|
57
|
-
# @param uncompressed_size [
|
58
|
-
# @param compressed_size [
|
57
|
+
# @param uncompressed_size [Integer] size of the uncompressed entry
|
58
|
+
# @param compressed_size [Integer] size of the compressed entry
|
59
59
|
# @param use_data_descriptor[Boolean] whether the entry uses a postfix data
|
60
60
|
# descriptor to specify size
|
61
61
|
# @return self
|
data/lib/zip_kit/stream_crc32.rb
CHANGED
@@ -16,7 +16,7 @@ class ZipKit::StreamCRC32
|
|
16
16
|
# Compute a CRC32 value from an IO object. The object should respond to `read` and `eof?`
|
17
17
|
#
|
18
18
|
# @param io[IO] the IO to read the data from
|
19
|
-
# @return [
|
19
|
+
# @return [Integer] the computed CRC32 value
|
20
20
|
def self.from_io(io)
|
21
21
|
# If we can specify the string capacity upfront we will not have to resize
|
22
22
|
# the string during operation. This saves time but is only available on
|
@@ -43,7 +43,7 @@ class ZipKit::StreamCRC32
|
|
43
43
|
|
44
44
|
# Returns the CRC32 value computed so far
|
45
45
|
#
|
46
|
-
# @return [
|
46
|
+
# @return [Integer] the updated CRC32 value for all the blobs so far
|
47
47
|
def to_i
|
48
48
|
@crc
|
49
49
|
end
|
@@ -51,9 +51,9 @@ class ZipKit::StreamCRC32
|
|
51
51
|
# Appends a known CRC32 value to the current one, and combines the
|
52
52
|
# contained CRC32 value in-place.
|
53
53
|
#
|
54
|
-
# @param crc32[
|
55
|
-
# @param blob_size[
|
56
|
-
# @return [
|
54
|
+
# @param crc32[Integer] the CRC32 value to append
|
55
|
+
# @param blob_size[Integer] the size of the daata the `crc32` is computed from
|
56
|
+
# @return [Integer] the updated CRC32 value for all the blobs so far
|
57
57
|
def append(crc32, blob_size)
|
58
58
|
@crc = Zlib.crc32_combine(@crc, crc32, blob_size)
|
59
59
|
end
|
data/lib/zip_kit/version.rb
CHANGED
data/lib/zip_kit/write_shovel.rb
CHANGED
@@ -14,7 +14,7 @@ module ZipKit::WriteShovel
|
|
14
14
|
# a target for `IO.copy_stream(from, to)`
|
15
15
|
#
|
16
16
|
# @param bytes[String] the binary string to write (part of the uncompressed file)
|
17
|
-
# @return [
|
17
|
+
# @return [Integer] the number of bytes written (will always be the bytesize of `bytes`)
|
18
18
|
def write(bytes)
|
19
19
|
self << bytes
|
20
20
|
bytes.bytesize
|
data/lib/zip_kit/zip_writer.rb
CHANGED
@@ -64,12 +64,12 @@ class ZipKit::ZipWriter
|
|
64
64
|
#
|
65
65
|
# @param io[#<<] the buffer to write the local file header to
|
66
66
|
# @param filename[String] the name of the file in the archive
|
67
|
-
# @param compressed_size[
|
68
|
-
# @param uncompressed_size[
|
69
|
-
# @param crc32[
|
67
|
+
# @param compressed_size[Integer] The size of the compressed (or stored) data - how much space it uses in the ZIP
|
68
|
+
# @param uncompressed_size[Integer] The size of the file once extracted
|
69
|
+
# @param crc32[Integer] The CRC32 checksum of the file
|
70
70
|
# @param mtime[Time] the modification time to be recorded in the ZIP
|
71
|
-
# @param gp_flags[
|
72
|
-
# @param storage_mode[
|
71
|
+
# @param gp_flags[Integer] bit-packed general purpose flags
|
72
|
+
# @param storage_mode[Integer] 8 for deflated, 0 for stored...
|
73
73
|
# @return [void]
|
74
74
|
def write_local_file_header(io:, filename:, compressed_size:, uncompressed_size:, crc32:, gp_flags:, mtime:, storage_mode:)
|
75
75
|
requires_zip64 = compressed_size > FOUR_BYTE_MAX_UINT || uncompressed_size > FOUR_BYTE_MAX_UINT
|
@@ -136,11 +136,11 @@ class ZipKit::ZipWriter
|
|
136
136
|
#
|
137
137
|
# @param io[#<<] the buffer to write the local file header to
|
138
138
|
# @param filename[String] the name of the file in the archive
|
139
|
-
# @param compressed_size[
|
140
|
-
# @param uncompressed_size[
|
141
|
-
# @param crc32[
|
139
|
+
# @param compressed_size[Integer] The size of the compressed (or stored) data - how much space it uses in the ZIP
|
140
|
+
# @param uncompressed_size[Integer] The size of the file once extracted
|
141
|
+
# @param crc32[Integer] The CRC32 checksum of the file
|
142
142
|
# @param mtime[Time] the modification time to be recorded in the ZIP
|
143
|
-
# @param gp_flags[
|
143
|
+
# @param gp_flags[Integer] bit-packed general purpose flags
|
144
144
|
# @param unix_permissions[Integer] the permissions for the file, or nil for the default to be used
|
145
145
|
# @return [void]
|
146
146
|
def write_central_directory_file_header(io:,
|
@@ -253,9 +253,9 @@ class ZipKit::ZipWriter
|
|
253
253
|
# the data descriptor will have the sizes written out as 8-byte values instead of 4-byte values.
|
254
254
|
#
|
255
255
|
# @param io[#<<] the buffer to write the local file header to
|
256
|
-
# @param crc32[
|
257
|
-
# @param compressed_size[
|
258
|
-
# @param uncompressed_size[
|
256
|
+
# @param crc32[Integer] The CRC32 checksum of the file
|
257
|
+
# @param compressed_size[Integer] The size of the compressed (or stored) data - how much space it uses in the ZIP
|
258
|
+
# @param uncompressed_size[Integer] The size of the file once extracted
|
259
259
|
# @return [void]
|
260
260
|
def write_data_descriptor(io:, compressed_size:, uncompressed_size:, crc32:)
|
261
261
|
# Although not originally assigned a signature, the value
|
@@ -282,9 +282,9 @@ class ZipKit::ZipWriter
|
|
282
282
|
# Writes the "end of central directory record" (including the Zip6 salient bits if necessary)
|
283
283
|
#
|
284
284
|
# @param io[#<<] the buffer to write the central directory to.
|
285
|
-
# @param start_of_central_directory_location[
|
286
|
-
# @param central_directory_size[
|
287
|
-
# @param num_files_in_archive[
|
285
|
+
# @param start_of_central_directory_location[Integer] byte offset of the start of central directory form the beginning of ZIP file
|
286
|
+
# @param central_directory_size[Integer] the size of the central directory (only file headers) in bytes
|
287
|
+
# @param num_files_in_archive[Integer] How many files the archive contains
|
288
288
|
# @param comment[String] the comment for the archive (defaults to ZIP_KIT_COMMENT)
|
289
289
|
# @return [void]
|
290
290
|
def write_end_of_central_directory(io:, start_of_central_directory_location:, central_directory_size:, num_files_in_archive:, comment: ZIP_KIT_COMMENT)
|
@@ -386,8 +386,8 @@ class ZipKit::ZipWriter
|
|
386
386
|
|
387
387
|
# Writes the Zip64 extra field for the local file header. Will be used by `write_local_file_header` when any sizes given to it warrant that.
|
388
388
|
#
|
389
|
-
# @param compressed_size[
|
390
|
-
# @param uncompressed_size[
|
389
|
+
# @param compressed_size[Integer] The size of the compressed (or stored) data - how much space it uses in the ZIP
|
390
|
+
# @param uncompressed_size[Integer] The size of the file once extracted
|
391
391
|
# @return [String]
|
392
392
|
def zip_64_extra_for_local_file_header(compressed_size:, uncompressed_size:)
|
393
393
|
data_and_packspecs = [
|
@@ -460,9 +460,9 @@ class ZipKit::ZipWriter
|
|
460
460
|
# Writes the Zip64 extra field for the central directory header.It differs from the extra used in the local file header because it
|
461
461
|
# also contains the location of the local file header in the ZIP as an 8-byte int.
|
462
462
|
#
|
463
|
-
# @param compressed_size[
|
464
|
-
# @param uncompressed_size[
|
465
|
-
# @param local_file_header_location[
|
463
|
+
# @param compressed_size[Integer] The size of the compressed (or stored) data - how much space it uses in the ZIP
|
464
|
+
# @param uncompressed_size[Integer] The size of the file once extracted
|
465
|
+
# @param local_file_header_location[Integer] Byte offset of the start of the local file header from the beginning of the ZIP archive
|
466
466
|
# @return [String]
|
467
467
|
def zip_64_extra_for_central_directory_file_header(compressed_size:, uncompressed_size:, local_file_header_location:)
|
468
468
|
data_and_packspecs = [
|
data/rbi/zip_kit.rbi
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# typed: strong
|
2
2
|
module ZipKit
|
3
|
-
VERSION = T.let("6.3.
|
3
|
+
VERSION = T.let("6.3.1", T.untyped)
|
4
4
|
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
end
|
@@ -572,7 +572,7 @@ module ZipKit
|
|
572
572
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
573
573
|
#
|
574
574
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
575
|
-
sig { params(bytes: String).returns(
|
575
|
+
sig { params(bytes: String).returns(Integer) }
|
576
576
|
def write(bytes); end
|
577
577
|
|
578
578
|
# Is used internally by Streamer to keep track of entries in the archive during writing.
|
@@ -686,7 +686,7 @@ module ZipKit
|
|
686
686
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
687
687
|
#
|
688
688
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
689
|
-
sig { params(bytes: String).returns(
|
689
|
+
sig { params(bytes: String).returns(Integer) }
|
690
690
|
def write(bytes); end
|
691
691
|
end
|
692
692
|
|
@@ -755,7 +755,7 @@ module ZipKit
|
|
755
755
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
756
756
|
#
|
757
757
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
758
|
-
sig { params(bytes: String).returns(
|
758
|
+
sig { params(bytes: String).returns(Integer) }
|
759
759
|
def write(bytes); end
|
760
760
|
end
|
761
761
|
|
@@ -793,7 +793,7 @@ module ZipKit
|
|
793
793
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
794
794
|
#
|
795
795
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
796
|
-
sig { params(bytes: String).returns(
|
796
|
+
sig { params(bytes: String).returns(Integer) }
|
797
797
|
def write(bytes); end
|
798
798
|
end
|
799
799
|
end
|
@@ -835,11 +835,11 @@ module ZipKit
|
|
835
835
|
# _@param_ `n_bytes` — how many bytes to read, or `nil` to read all the way to the end
|
836
836
|
#
|
837
837
|
# _@return_ — the read bytes
|
838
|
-
sig { params(n_bytes: T.nilable(
|
838
|
+
sig { params(n_bytes: T.nilable(Integer)).returns(String) }
|
839
839
|
def read(n_bytes = nil); end
|
840
840
|
|
841
841
|
# Returns the current pointer position within the IO
|
842
|
-
sig { returns(
|
842
|
+
sig { returns(Integer) }
|
843
843
|
def tell; end
|
844
844
|
|
845
845
|
# Only used internally when reading the remote ZIP.
|
@@ -933,12 +933,12 @@ end, T.untyped)
|
|
933
933
|
params(
|
934
934
|
io: T.untyped,
|
935
935
|
filename: String,
|
936
|
-
compressed_size:
|
937
|
-
uncompressed_size:
|
938
|
-
crc32:
|
939
|
-
gp_flags:
|
936
|
+
compressed_size: Integer,
|
937
|
+
uncompressed_size: Integer,
|
938
|
+
crc32: Integer,
|
939
|
+
gp_flags: Integer,
|
940
940
|
mtime: Time,
|
941
|
-
storage_mode:
|
941
|
+
storage_mode: Integer
|
942
942
|
).void
|
943
943
|
end
|
944
944
|
def write_local_file_header(io:, filename:, compressed_size:, uncompressed_size:, crc32:, gp_flags:, mtime:, storage_mode:); end
|
@@ -968,12 +968,12 @@ end, T.untyped)
|
|
968
968
|
params(
|
969
969
|
io: T.untyped,
|
970
970
|
local_file_header_location: T.untyped,
|
971
|
-
gp_flags:
|
971
|
+
gp_flags: Integer,
|
972
972
|
storage_mode: T.untyped,
|
973
|
-
compressed_size:
|
974
|
-
uncompressed_size:
|
973
|
+
compressed_size: Integer,
|
974
|
+
uncompressed_size: Integer,
|
975
975
|
mtime: Time,
|
976
|
-
crc32:
|
976
|
+
crc32: Integer,
|
977
977
|
filename: String,
|
978
978
|
unix_permissions: T.nilable(Integer)
|
979
979
|
).void
|
@@ -995,9 +995,9 @@ end, T.untyped)
|
|
995
995
|
sig do
|
996
996
|
params(
|
997
997
|
io: T.untyped,
|
998
|
-
compressed_size:
|
999
|
-
uncompressed_size:
|
1000
|
-
crc32:
|
998
|
+
compressed_size: Integer,
|
999
|
+
uncompressed_size: Integer,
|
1000
|
+
crc32: Integer
|
1001
1001
|
).void
|
1002
1002
|
end
|
1003
1003
|
def write_data_descriptor(io:, compressed_size:, uncompressed_size:, crc32:); end
|
@@ -1017,9 +1017,9 @@ end, T.untyped)
|
|
1017
1017
|
sig do
|
1018
1018
|
params(
|
1019
1019
|
io: T.untyped,
|
1020
|
-
start_of_central_directory_location:
|
1021
|
-
central_directory_size:
|
1022
|
-
num_files_in_archive:
|
1020
|
+
start_of_central_directory_location: Integer,
|
1021
|
+
central_directory_size: Integer,
|
1022
|
+
num_files_in_archive: Integer,
|
1023
1023
|
comment: String
|
1024
1024
|
).void
|
1025
1025
|
end
|
@@ -1030,7 +1030,7 @@ end, T.untyped)
|
|
1030
1030
|
# _@param_ `compressed_size` — The size of the compressed (or stored) data - how much space it uses in the ZIP
|
1031
1031
|
#
|
1032
1032
|
# _@param_ `uncompressed_size` — The size of the file once extracted
|
1033
|
-
sig { params(compressed_size:
|
1033
|
+
sig { params(compressed_size: Integer, uncompressed_size: Integer).returns(String) }
|
1034
1034
|
def zip_64_extra_for_local_file_header(compressed_size:, uncompressed_size:); end
|
1035
1035
|
|
1036
1036
|
# sord omit - no YARD type given for "mtime", using untyped
|
@@ -1053,7 +1053,7 @@ end, T.untyped)
|
|
1053
1053
|
# _@param_ `uncompressed_size` — The size of the file once extracted
|
1054
1054
|
#
|
1055
1055
|
# _@param_ `local_file_header_location` — Byte offset of the start of the local file header from the beginning of the ZIP archive
|
1056
|
-
sig { params(compressed_size:
|
1056
|
+
sig { params(compressed_size: Integer, uncompressed_size: Integer, local_file_header_location: Integer).returns(String) }
|
1057
1057
|
def zip_64_extra_for_central_directory_file_header(compressed_size:, uncompressed_size:, local_file_header_location:); end
|
1058
1058
|
|
1059
1059
|
# sord omit - no YARD type given for "t", using untyped
|
@@ -1126,7 +1126,7 @@ end, T.untyped)
|
|
1126
1126
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
1127
1127
|
#
|
1128
1128
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
1129
|
-
sig { params(bytes: String).returns(
|
1129
|
+
sig { params(bytes: String).returns(Integer) }
|
1130
1130
|
def write(bytes); end
|
1131
1131
|
end
|
1132
1132
|
|
@@ -1286,7 +1286,7 @@ end, T.untyped)
|
|
1286
1286
|
# _@param_ `io` — an IO-ish object the ZIP file can be read from
|
1287
1287
|
#
|
1288
1288
|
# _@return_ — the parsed local header entry and
|
1289
|
-
sig { params(io: T.untyped).returns(T::Array[T.any(ZipEntry,
|
1289
|
+
sig { params(io: T.untyped).returns(T::Array[T.any(ZipEntry, Integer)]) }
|
1290
1290
|
def read_local_file_header(io:); end
|
1291
1291
|
|
1292
1292
|
# sord duck - #seek looks like a duck type, replacing with untyped
|
@@ -1299,13 +1299,13 @@ end, T.untyped)
|
|
1299
1299
|
# header offset given will be the compressed data offset of the entry
|
1300
1300
|
# (read starting at this offset to get the data).
|
1301
1301
|
#
|
1302
|
-
# local file header is supposed to begin @return [
|
1302
|
+
# local file header is supposed to begin @return [Integer] absolute offset
|
1303
1303
|
# (0-based) of where the compressed data begins for this file within the ZIP
|
1304
1304
|
#
|
1305
1305
|
# _@param_ `io` — an IO-ish object the ZIP file can be read from
|
1306
1306
|
#
|
1307
1307
|
# _@param_ `local_file_header_offset` — absolute offset (0-based) where the
|
1308
|
-
sig { params(io: T.untyped, local_file_header_offset:
|
1308
|
+
sig { params(io: T.untyped, local_file_header_offset: Integer).returns(T.untyped) }
|
1309
1309
|
def get_compressed_data_offset(io:, local_file_header_offset:); end
|
1310
1310
|
|
1311
1311
|
# Parse an IO handle to a ZIP archive into an array of Entry objects, reading from the end
|
@@ -1502,7 +1502,7 @@ end, T.untyped)
|
|
1502
1502
|
|
1503
1503
|
# _@return_ — at what offset you should start reading
|
1504
1504
|
# for the compressed data in your original IO object
|
1505
|
-
sig { returns(
|
1505
|
+
sig { returns(Integer) }
|
1506
1506
|
def compressed_data_offset; end
|
1507
1507
|
|
1508
1508
|
# Tells whether the compressed data offset is already known for this entry
|
@@ -1514,7 +1514,7 @@ end, T.untyped)
|
|
1514
1514
|
sig { returns(T::Boolean) }
|
1515
1515
|
def uses_data_descriptor?; end
|
1516
1516
|
|
1517
|
-
# sord infer - inferred type of parameter "offset" as
|
1517
|
+
# sord infer - inferred type of parameter "offset" as Integer using getter's return type
|
1518
1518
|
# sord omit - no YARD return type given, using untyped
|
1519
1519
|
# Sets the offset at which the compressed data for this file starts in the ZIP.
|
1520
1520
|
# By default, the value will be set by the Reader for you. If you use delayed
|
@@ -1522,43 +1522,43 @@ end, T.untyped)
|
|
1522
1522
|
#
|
1523
1523
|
# entry.compressed_data_offset = reader.get_compressed_data_offset(io: file,
|
1524
1524
|
# local_file_header_offset: entry.local_header_offset)
|
1525
|
-
sig { params(offset:
|
1525
|
+
sig { params(offset: Integer).returns(T.untyped) }
|
1526
1526
|
def compressed_data_offset=(offset); end
|
1527
1527
|
|
1528
1528
|
# _@return_ — bit-packed version signature of the program that made the archive
|
1529
|
-
sig { returns(
|
1529
|
+
sig { returns(Integer) }
|
1530
1530
|
attr_accessor :made_by
|
1531
1531
|
|
1532
1532
|
# _@return_ — ZIP version support needed to extract this file
|
1533
|
-
sig { returns(
|
1533
|
+
sig { returns(Integer) }
|
1534
1534
|
attr_accessor :version_needed_to_extract
|
1535
1535
|
|
1536
1536
|
# _@return_ — bit-packed general purpose flags
|
1537
|
-
sig { returns(
|
1537
|
+
sig { returns(Integer) }
|
1538
1538
|
attr_accessor :gp_flags
|
1539
1539
|
|
1540
1540
|
# _@return_ — Storage mode (0 for stored, 8 for deflate)
|
1541
|
-
sig { returns(
|
1541
|
+
sig { returns(Integer) }
|
1542
1542
|
attr_accessor :storage_mode
|
1543
1543
|
|
1544
1544
|
# _@return_ — the bit-packed DOS time
|
1545
|
-
sig { returns(
|
1545
|
+
sig { returns(Integer) }
|
1546
1546
|
attr_accessor :dos_time
|
1547
1547
|
|
1548
1548
|
# _@return_ — the bit-packed DOS date
|
1549
|
-
sig { returns(
|
1549
|
+
sig { returns(Integer) }
|
1550
1550
|
attr_accessor :dos_date
|
1551
1551
|
|
1552
1552
|
# _@return_ — the CRC32 checksum of this file
|
1553
|
-
sig { returns(
|
1553
|
+
sig { returns(Integer) }
|
1554
1554
|
attr_accessor :crc32
|
1555
1555
|
|
1556
1556
|
# _@return_ — size of compressed file data in the ZIP
|
1557
|
-
sig { returns(
|
1557
|
+
sig { returns(Integer) }
|
1558
1558
|
attr_accessor :compressed_size
|
1559
1559
|
|
1560
1560
|
# _@return_ — size of the file once uncompressed
|
1561
|
-
sig { returns(
|
1561
|
+
sig { returns(Integer) }
|
1562
1562
|
attr_accessor :uncompressed_size
|
1563
1563
|
|
1564
1564
|
# _@return_ — the filename
|
@@ -1566,20 +1566,20 @@ end, T.untyped)
|
|
1566
1566
|
attr_accessor :filename
|
1567
1567
|
|
1568
1568
|
# _@return_ — disk number where this file starts
|
1569
|
-
sig { returns(
|
1569
|
+
sig { returns(Integer) }
|
1570
1570
|
attr_accessor :disk_number_start
|
1571
1571
|
|
1572
1572
|
# _@return_ — internal attributes of the file
|
1573
|
-
sig { returns(
|
1573
|
+
sig { returns(Integer) }
|
1574
1574
|
attr_accessor :internal_attrs
|
1575
1575
|
|
1576
1576
|
# _@return_ — external attributes of the file
|
1577
|
-
sig { returns(
|
1577
|
+
sig { returns(Integer) }
|
1578
1578
|
attr_accessor :external_attrs
|
1579
1579
|
|
1580
1580
|
# _@return_ — at what offset the local file header starts
|
1581
1581
|
# in your original IO object
|
1582
|
-
sig { returns(
|
1582
|
+
sig { returns(Integer) }
|
1583
1583
|
attr_accessor :local_file_header_offset
|
1584
1584
|
|
1585
1585
|
# _@return_ — the file comment
|
@@ -1635,7 +1635,7 @@ end, T.untyped)
|
|
1635
1635
|
# _@param_ `io` — the IO to read the data from
|
1636
1636
|
#
|
1637
1637
|
# _@return_ — the computed CRC32 value
|
1638
|
-
sig { params(io: IO).returns(
|
1638
|
+
sig { params(io: IO).returns(Integer) }
|
1639
1639
|
def self.from_io(io); end
|
1640
1640
|
|
1641
1641
|
# Creates a new streaming CRC32 calculator
|
@@ -1651,7 +1651,7 @@ end, T.untyped)
|
|
1651
1651
|
# Returns the CRC32 value computed so far
|
1652
1652
|
#
|
1653
1653
|
# _@return_ — the updated CRC32 value for all the blobs so far
|
1654
|
-
sig { returns(
|
1654
|
+
sig { returns(Integer) }
|
1655
1655
|
def to_i; end
|
1656
1656
|
|
1657
1657
|
# Appends a known CRC32 value to the current one, and combines the
|
@@ -1662,7 +1662,7 @@ end, T.untyped)
|
|
1662
1662
|
# _@param_ `blob_size` — the size of the daata the `crc32` is computed from
|
1663
1663
|
#
|
1664
1664
|
# _@return_ — the updated CRC32 value for all the blobs so far
|
1665
|
-
sig { params(crc32:
|
1665
|
+
sig { params(crc32: Integer, blob_size: Integer).returns(Integer) }
|
1666
1666
|
def append(crc32, blob_size); end
|
1667
1667
|
|
1668
1668
|
# Writes the given data to the output stream. Allows the object to be used as
|
@@ -1671,7 +1671,7 @@ end, T.untyped)
|
|
1671
1671
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
1672
1672
|
#
|
1673
1673
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
1674
|
-
sig { params(bytes: String).returns(
|
1674
|
+
sig { params(bytes: String).returns(Integer) }
|
1675
1675
|
def write(bytes); end
|
1676
1676
|
end
|
1677
1677
|
|
@@ -1741,7 +1741,7 @@ end, T.untyped)
|
|
1741
1741
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
1742
1742
|
#
|
1743
1743
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
1744
|
-
sig { params(bytes: String).returns(
|
1744
|
+
sig { params(bytes: String).returns(Integer) }
|
1745
1745
|
def write(bytes); end
|
1746
1746
|
end
|
1747
1747
|
|
@@ -1801,7 +1801,7 @@ end, T.untyped)
|
|
1801
1801
|
# _@param_ `output_io` — the stream to write to (should respond to `:<<`)
|
1802
1802
|
#
|
1803
1803
|
# _@return_ — number of bytes written to `output_io`
|
1804
|
-
sig { params(output_io: IO).returns(
|
1804
|
+
sig { params(output_io: IO).returns(Integer) }
|
1805
1805
|
def self.write_terminator(output_io); end
|
1806
1806
|
|
1807
1807
|
# Compress a given binary string and flush the deflate stream at byte boundary.
|
@@ -1812,7 +1812,7 @@ end, T.untyped)
|
|
1812
1812
|
# _@param_ `level` — Zlib compression level (defaults to `Zlib::DEFAULT_COMPRESSION`)
|
1813
1813
|
#
|
1814
1814
|
# _@return_ — compressed bytes
|
1815
|
-
sig { params(bytes: String, level:
|
1815
|
+
sig { params(bytes: String, level: Integer).returns(String) }
|
1816
1816
|
def self.deflate_chunk(bytes, level: Zlib::DEFAULT_COMPRESSION); end
|
1817
1817
|
|
1818
1818
|
# Compress the contents of input_io into output_io, in blocks
|
@@ -1838,9 +1838,9 @@ end, T.untyped)
|
|
1838
1838
|
params(
|
1839
1839
|
input_io: IO,
|
1840
1840
|
output_io: IO,
|
1841
|
-
level:
|
1842
|
-
block_size:
|
1843
|
-
).returns(
|
1841
|
+
level: Integer,
|
1842
|
+
block_size: Integer
|
1843
|
+
).returns(Integer)
|
1844
1844
|
end
|
1845
1845
|
def self.deflate_in_blocks_and_terminate(input_io, output_io, level: Zlib::DEFAULT_COMPRESSION, block_size: DEFAULT_BLOCKSIZE); end
|
1846
1846
|
|
@@ -1864,9 +1864,9 @@ end, T.untyped)
|
|
1864
1864
|
params(
|
1865
1865
|
input_io: IO,
|
1866
1866
|
output_io: IO,
|
1867
|
-
level:
|
1868
|
-
block_size:
|
1869
|
-
).returns(
|
1867
|
+
level: Integer,
|
1868
|
+
block_size: Integer
|
1869
|
+
).returns(Integer)
|
1870
1870
|
end
|
1871
1871
|
def self.deflate_in_blocks(input_io, output_io, level: Zlib::DEFAULT_COMPRESSION, block_size: DEFAULT_BLOCKSIZE); end
|
1872
1872
|
end
|
@@ -1892,7 +1892,7 @@ end, T.untyped)
|
|
1892
1892
|
# _@param_ `kwargs_for_streamer_new` — Any options to pass to Streamer, see {Streamer#initialize}
|
1893
1893
|
#
|
1894
1894
|
# _@return_ — the size of the resulting archive, in bytes
|
1895
|
-
sig { params(kwargs_for_streamer_new: T.untyped, blk: T.proc.params(
|
1895
|
+
sig { params(kwargs_for_streamer_new: T.untyped, blk: T.proc.params(estimator: SizeEstimator).void).returns(Integer) }
|
1896
1896
|
def self.estimate(**kwargs_for_streamer_new, &blk); end
|
1897
1897
|
|
1898
1898
|
# Add a fake entry to the archive, to see how big it is going to be in the end.
|
@@ -1906,7 +1906,7 @@ end, T.untyped)
|
|
1906
1906
|
# _@param_ `use_data_descriptor` — whether the entry uses a postfix
|
1907
1907
|
#
|
1908
1908
|
# _@return_ — self
|
1909
|
-
sig { params(filename: String, size:
|
1909
|
+
sig { params(filename: String, size: Integer, use_data_descriptor: T::Boolean).returns(T.untyped) }
|
1910
1910
|
def add_stored_entry(filename:, size:, use_data_descriptor: false); end
|
1911
1911
|
|
1912
1912
|
# Add a fake entry to the archive, to see how big it is going to be in the end.
|
@@ -1923,8 +1923,8 @@ end, T.untyped)
|
|
1923
1923
|
sig do
|
1924
1924
|
params(
|
1925
1925
|
filename: String,
|
1926
|
-
uncompressed_size:
|
1927
|
-
compressed_size:
|
1926
|
+
uncompressed_size: Integer,
|
1927
|
+
compressed_size: Integer,
|
1928
1928
|
use_data_descriptor: T::Boolean
|
1929
1929
|
).returns(T.untyped)
|
1930
1930
|
end
|
@@ -1972,7 +1972,7 @@ end, T.untyped)
|
|
1972
1972
|
# _@param_ `bytes` — the binary string to write (part of the uncompressed file)
|
1973
1973
|
#
|
1974
1974
|
# _@return_ — the number of bytes written (will always be the bytesize of `bytes`)
|
1975
|
-
sig { params(bytes: String).returns(
|
1975
|
+
sig { params(bytes: String).returns(Integer) }
|
1976
1976
|
def write(bytes); end
|
1977
1977
|
end
|
1978
1978
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zip_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.3.
|
4
|
+
version: 6.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: exe
|
14
14
|
cert_chain: []
|
15
|
-
date: 2024-
|
15
|
+
date: 2024-08-11 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
@@ -299,10 +299,8 @@ executables: []
|
|
299
299
|
extensions: []
|
300
300
|
extra_rdoc_files: []
|
301
301
|
files:
|
302
|
-
- ".document"
|
303
302
|
- ".github/workflows/ci.yml"
|
304
303
|
- ".gitignore"
|
305
|
-
- ".rspec"
|
306
304
|
- ".standard.yml"
|
307
305
|
- ".yardopts"
|
308
306
|
- CHANGELOG.md
|
@@ -314,7 +312,6 @@ files:
|
|
314
312
|
- README.md
|
315
313
|
- RUBYZIP_DIFFERENCES.md
|
316
314
|
- Rakefile
|
317
|
-
- bench/buffered_crc32_bench.rb
|
318
315
|
- examples/archive_size_estimate.rb
|
319
316
|
- examples/config.ru
|
320
317
|
- examples/deferred_write.rb
|
@@ -374,7 +371,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
374
371
|
- !ruby/object:Gem::Version
|
375
372
|
version: '0'
|
376
373
|
requirements: []
|
377
|
-
rubygems_version: 3.
|
374
|
+
rubygems_version: 3.5.3
|
378
375
|
signing_key:
|
379
376
|
specification_version: 4
|
380
377
|
summary: Stream out ZIP files from Ruby. Successor to zip_tricks.
|
data/.document
DELETED
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
@@ -1,109 +0,0 @@
|
|
1
|
-
require "bundler"
|
2
|
-
Bundler.setup
|
3
|
-
|
4
|
-
require "benchmark"
|
5
|
-
require "benchmark/ips"
|
6
|
-
require_relative "../lib/zip_kit"
|
7
|
-
|
8
|
-
n_bytes = 5 * 1024 * 1024
|
9
|
-
r = Random.new
|
10
|
-
bytes = (0...n_bytes).map { r.bytes(1) }
|
11
|
-
buffer_sizes = [
|
12
|
-
1,
|
13
|
-
256,
|
14
|
-
512,
|
15
|
-
1024,
|
16
|
-
8 * 1024,
|
17
|
-
16 * 1024,
|
18
|
-
32 * 1024,
|
19
|
-
64 * 1024,
|
20
|
-
128 * 1024,
|
21
|
-
256 * 1024,
|
22
|
-
512 * 1024,
|
23
|
-
1024 * 1024,
|
24
|
-
2 * 1024 * 1024
|
25
|
-
]
|
26
|
-
|
27
|
-
Benchmark.ips do |x|
|
28
|
-
x.config(time: 5, warmup: 2)
|
29
|
-
buffer_sizes.each do |buf_size|
|
30
|
-
x.report "Single-byte <<-writes of #{n_bytes} using a #{buf_size} byte buffer" do
|
31
|
-
crc = ZipKit::WriteBuffer.new(ZipKit::StreamCRC32.new, buf_size)
|
32
|
-
bytes.each { |b| crc << b }
|
33
|
-
crc.to_i
|
34
|
-
end
|
35
|
-
end
|
36
|
-
x.compare!
|
37
|
-
end
|
38
|
-
|
39
|
-
__END__
|
40
|
-
|
41
|
-
Warming up --------------------------------------
|
42
|
-
Single-byte <<-writes of 5242880 using a 1 byte buffer
|
43
|
-
1.000 i/100ms
|
44
|
-
Single-byte <<-writes of 5242880 using a 256 byte buffer
|
45
|
-
1.000 i/100ms
|
46
|
-
Single-byte <<-writes of 5242880 using a 512 byte buffer
|
47
|
-
1.000 i/100ms
|
48
|
-
Single-byte <<-writes of 5242880 using a 1024 byte buffer
|
49
|
-
1.000 i/100ms
|
50
|
-
Single-byte <<-writes of 5242880 using a 8192 byte buffer
|
51
|
-
1.000 i/100ms
|
52
|
-
Single-byte <<-writes of 5242880 using a 16384 byte buffer
|
53
|
-
1.000 i/100ms
|
54
|
-
Single-byte <<-writes of 5242880 using a 32768 byte buffer
|
55
|
-
1.000 i/100ms
|
56
|
-
Single-byte <<-writes of 5242880 using a 65536 byte buffer
|
57
|
-
1.000 i/100ms
|
58
|
-
Single-byte <<-writes of 5242880 using a 131072 byte buffer
|
59
|
-
1.000 i/100ms
|
60
|
-
Single-byte <<-writes of 5242880 using a 262144 byte buffer
|
61
|
-
1.000 i/100ms
|
62
|
-
Single-byte <<-writes of 5242880 using a 524288 byte buffer
|
63
|
-
1.000 i/100ms
|
64
|
-
Single-byte <<-writes of 5242880 using a 1048576 byte buffer
|
65
|
-
1.000 i/100ms
|
66
|
-
Single-byte <<-writes of 5242880 using a 2097152 byte buffer
|
67
|
-
1.000 i/100ms
|
68
|
-
Calculating -------------------------------------
|
69
|
-
Single-byte <<-writes of 5242880 using a 1 byte buffer
|
70
|
-
0.054 (± 0.0%) i/s - 1.000 in 18.383019s
|
71
|
-
Single-byte <<-writes of 5242880 using a 256 byte buffer
|
72
|
-
0.121 (± 0.0%) i/s - 1.000 in 8.286061s
|
73
|
-
Single-byte <<-writes of 5242880 using a 512 byte buffer
|
74
|
-
0.124 (± 0.0%) i/s - 1.000 in 8.038112s
|
75
|
-
Single-byte <<-writes of 5242880 using a 1024 byte buffer
|
76
|
-
0.128 (± 0.0%) i/s - 1.000 in 7.828562s
|
77
|
-
Single-byte <<-writes of 5242880 using a 8192 byte buffer
|
78
|
-
0.123 (± 0.0%) i/s - 1.000 in 8.121586s
|
79
|
-
Single-byte <<-writes of 5242880 using a 16384 byte buffer
|
80
|
-
0.127 (± 0.0%) i/s - 1.000 in 7.872240s
|
81
|
-
Single-byte <<-writes of 5242880 using a 32768 byte buffer
|
82
|
-
0.126 (± 0.0%) i/s - 1.000 in 7.911816s
|
83
|
-
Single-byte <<-writes of 5242880 using a 65536 byte buffer
|
84
|
-
0.126 (± 0.0%) i/s - 1.000 in 7.917318s
|
85
|
-
Single-byte <<-writes of 5242880 using a 131072 byte buffer
|
86
|
-
0.127 (± 0.0%) i/s - 1.000 in 7.897223s
|
87
|
-
Single-byte <<-writes of 5242880 using a 262144 byte buffer
|
88
|
-
0.130 (± 0.0%) i/s - 1.000 in 7.675608s
|
89
|
-
Single-byte <<-writes of 5242880 using a 524288 byte buffer
|
90
|
-
0.130 (± 0.0%) i/s - 1.000 in 7.679886s
|
91
|
-
Single-byte <<-writes of 5242880 using a 1048576 byte buffer
|
92
|
-
0.128 (± 0.0%) i/s - 1.000 in 7.788439s
|
93
|
-
Single-byte <<-writes of 5242880 using a 2097152 byte buffer
|
94
|
-
0.128 (± 0.0%) i/s - 1.000 in 7.797839s
|
95
|
-
|
96
|
-
Comparison:
|
97
|
-
Single-byte <<-writes of 5242880 using a 262144 byte buffer: 0.1 i/s
|
98
|
-
Single-byte <<-writes of 5242880 using a 524288 byte buffer: 0.1 i/s - 1.00x slower
|
99
|
-
Single-byte <<-writes of 5242880 using a 1048576 byte buffer: 0.1 i/s - 1.01x slower
|
100
|
-
Single-byte <<-writes of 5242880 using a 2097152 byte buffer: 0.1 i/s - 1.02x slower
|
101
|
-
Single-byte <<-writes of 5242880 using a 1024 byte buffer: 0.1 i/s - 1.02x slower
|
102
|
-
Single-byte <<-writes of 5242880 using a 16384 byte buffer: 0.1 i/s - 1.03x slower
|
103
|
-
Single-byte <<-writes of 5242880 using a 131072 byte buffer: 0.1 i/s - 1.03x slower
|
104
|
-
Single-byte <<-writes of 5242880 using a 32768 byte buffer: 0.1 i/s - 1.03x slower
|
105
|
-
Single-byte <<-writes of 5242880 using a 65536 byte buffer: 0.1 i/s - 1.03x slower
|
106
|
-
Single-byte <<-writes of 5242880 using a 512 byte buffer: 0.1 i/s - 1.05x slower
|
107
|
-
Single-byte <<-writes of 5242880 using a 8192 byte buffer: 0.1 i/s - 1.06x slower
|
108
|
-
Single-byte <<-writes of 5242880 using a 256 byte buffer: 0.1 i/s - 1.08x slower
|
109
|
-
Single-byte <<-writes of 5242880 using a 1 byte buffer: 0.1 i/s - 2.39x slower
|