aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/zip_spec.cr5
-rw-r--r--src/zip.cr65
2 files changed, 58 insertions, 12 deletions
diff --git a/spec/zip_spec.cr b/spec/zip_spec.cr
index 7505fd3..cae6de9 100644
--- a/spec/zip_spec.cr
+++ b/spec/zip_spec.cr
@@ -54,3 +54,8 @@ describe Zip::Writer do
end
end
end
+
+describe Zip::Reader do
+ Zip.read(File.join(TEST_DIR, "test-empty.zip")) do |zip|
+ end
+end
diff --git a/src/zip.cr b/src/zip.cr
index 5b6f4c4..4761695 100644
--- a/src/zip.cr
+++ b/src/zip.cr
@@ -4,7 +4,7 @@ require "zlib"
#
# TODO:
# [x] date/time
-# [x] reader
+# [ ] reader
# [ ] documentation
# [ ] full tests
# [ ] zip64
@@ -182,10 +182,25 @@ module Zip
# TODO
class Reader
- def initialize(path : String)
+ getter? :closed, :sync_close
+
+ def initialize(
+ @io : IO,
+ @pos : UInt32 = 0,
+ @sync_close : Bool = false,
+ )
+ @closed = false
end
- def initialize(io : IO)
+ private def assert_open
+ raise Error.new("already closed") if closed?
+ end
+
+ def close
+ assert_open
+
+ @io.close if @sync_close
+ @closed = true
end
end
@@ -387,9 +402,9 @@ module Zip
path_len = path.bytesize
# check file path
- raise "empty file path" if path_len == 0
- raise "file path too long" if path_len >= UInt16::MAX
- raise "file path contains leading slash" if path[0] == '/'
+ raise Error.new("empty file path") if path_len == 0
+ raise Error.new("file path too long") if path_len >= UInt16::MAX
+ raise Error.new("file path contains leading slash") if path[0] == '/'
# write magic (u32), version needed (u16), flags (u16), and
# compression method (u16)
@@ -431,7 +446,7 @@ module Zip
when CompressionMethod::DEFLATE
compress_deflate(@io, dst_io)
else
- raise "unsupported compression method"
+ raise Error.new("unsupported compression method: #{@method}")
end
end
@@ -543,6 +558,8 @@ module Zip
end
class Writer
+ getter? :closed
+
def initialize(
@io : IO,
@pos : UInt32 = 0,
@@ -554,12 +571,8 @@ module Zip
@src_pos = @pos
end
- def closed?
- @closed
- end
-
private def assert_open
- raise "already closed" if closed?
+ raise Error.new("already closed") if closed?
end
def bytes_written : UInt32
@@ -699,6 +712,7 @@ module Zip
&cb : Writer -> \
) : UInt32
r = 0_u32
+
begin
w = Writer.new(io, pos, comment, version)
cb.call(w)
@@ -724,4 +738,31 @@ module Zip
write(io, pos, comment, version, &cb)
end
end
+
+ def self.read(
+ io : IO,
+ pos : UInt32 = 0_u32,
+ sync_close : Bool = false,
+ &cb : Reader -> \
+ )
+ begin
+ r = Reader.new(io, pos, sync_close)
+ cb.call(r)
+ ensure
+ if r
+ r.close unless r.closed?
+ end
+ end
+
+ nil
+ end
+
+ def self.read(
+ path : String,
+ &cb : Reader -> \
+ )
+ File.open(path, "rb") do |io|
+ read(io, 0_u32, true, &cb)
+ end
+ end
end