Skip to content

Commit

Permalink
Zlib: split into Adler32, CRC32, Flate, Gzip and Zlib types
Browse files Browse the repository at this point in the history
Crystal provides access to the Adler32, CRC32, DEFLATE,
gzip and zlib algorithms/formats. It currently does
so by binding to zlib (also known as libz). However, zlib is
just an implementation detail: this shouldn't leak to type
and method names because if we eventually decide to
change the library used to implement these, or maybe
implement stuff in pure Crystal, we'll be stuck with this
name.

So, here we split the contents of the Zlib module into:
- Adler32, for the Adler32 checksum algorithm
- CRC32, for the CRC32 checksum algorithm
- Flate: for the DEFLATE compression format (RFC 1951),
providing Reader and Writer types (Inflate and Deflate could also
work, but Reader and Writer are more obvious and consistent.)
Flate is also the name used by Go to provide the same
functionality, so it will be familiar to some.
- Gzip: for the gzip archive format (RFC 1952), which is just
a small wrapper (header and checksum) around the DEFLATE
format. Reader and Writer are provided, together with access
to the first gzip header.
- Zlib: for the zlib archive format (RFC 1950), which is just
a small wrapper around the DEFLATE format too (here the
format is also named the same as the C library, which brings
a lot of confusion). Reader and Writer are provided.

By doing this we also remove the need to know how to use the
zlib C library, which requires users to provide a cryptic `windowBits`
argument to choose the desierd format.

Finally, we rename HTTP::DeflateHandler to HTTP::CompressHandler
because that's what it does: it compress responses in either
gzip or DEFLATE, but not always DEFLATE (so the name was
misleading).

All of this is a big breaking change, but should be easy to upgrade
existing code and makes the standard library more consistent and
organized.
  • Loading branch information
Ary Borenszweig committed Jan 29, 2017
1 parent df10240 commit bda40f8
Show file tree
Hide file tree
Showing 39 changed files with 1,266 additions and 584 deletions.
16 changes: 16 additions & 0 deletions spec/std/adler32_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require "spec"
require "adler32"

describe Adler32 do
it "should be able to calculate adler32" do
adler = Adler32.checksum("foo").to_s(16)
adler.should eq("2820145")
end

it "should be able to calculate adler32 combined" do
adler1 = Adler32.checksum("hello")
adler2 = Adler32.checksum(" world!")
combined = Adler32.combine(adler1, adler2, " world!".size)
Adler32.checksum("hello world!").should eq(combined)
end
end
16 changes: 16 additions & 0 deletions spec/std/crc32_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require "spec"
require "crc32"

describe CRC32 do
it "should be able to calculate crc32" do
crc = CRC32.checksum("foo").to_s(16)
crc.should eq("8c736521")
end

it "should be able to calculate crc32 combined" do
crc1 = CRC32.checksum("hello")
crc2 = CRC32.checksum(" world!")
combined = CRC32.combine(crc1, crc2, " world!".size)
CRC32.checksum("hello world!").should eq(combined)
end
end
47 changes: 47 additions & 0 deletions spec/std/flate/flate_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require "spec"
require "flate"

module Flate
describe Writer do
it "should be able to write" do
message = "this is a test string !!!!\n"
io = IO::Memory.new
writer = Writer.new(io)
writer.print message
writer.close

io.rewind
reader = Reader.new(io)
reader.gets_to_end.should eq(message)
end

it "can be closed without sync" do
io = IO::Memory.new
writer = Writer.new(io)
writer.close
writer.closed?.should be_true
io.closed?.should be_false

expect_raises IO::Error, "closed stream" do
writer.print "a"
end
end

it "can be closed with sync (1)" do
io = IO::Memory.new
writer = Writer.new(io, sync_close: true)
writer.close
writer.closed?.should be_true
io.closed?.should be_true
end

it "can be closed with sync (2)" do
io = IO::Memory.new
writer = Writer.new(io)
writer.sync_close = true
writer.close
writer.closed?.should be_true
io.closed?.should be_true
end
end
end
46 changes: 46 additions & 0 deletions spec/std/gzip/gzip_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require "spec"
require "gzip"

describe Gzip do
it "writes and reads to memory" do
io = IO::Memory.new

time = Time.new(2016, 1, 2)
os = 4_u8
extra = Bytes[1, 2, 3]
name = "foo.txt"
comment = "some comment"
contents = "hello world"

Gzip::Writer.open(io) do |gzip|
header = gzip.header
header.modification_time = time
header.os = os
header.extra = extra
header.name = name
header.comment = comment

io.bytesize.should eq(0)
gzip.flush
io.bytesize.should_not eq(0)

gzip.print contents
end

io.rewind

Gzip::Reader.open(io) do |gzip|
header = gzip.header.not_nil!
header.modification_time.should eq(time)
header.os.should eq(os)
header.extra.should eq(extra)
header.name.should eq(name)
header.comment.should eq(comment)

# Reading zero bytes is OK
gzip.read(Bytes.empty).should eq(0)

gzip.gets_to_end.should eq(contents)
end
end
end
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
require "spec"
require "http/server"

describe HTTP::DeflateHandler do
describe HTTP::CompressHandler do
it "doesn't deflates if doesn't have 'deflate' in Accept-Encoding header" do
io = IO::Memory.new
request = HTTP::Request.new("GET", "/")
response = HTTP::Server::Response.new(io)
context = HTTP::Server::Context.new(request, response)

handler = HTTP::DeflateHandler.new
handler = HTTP::CompressHandler.new
handler.next = HTTP::Handler::Proc.new do |ctx|
ctx.response.print "Hello"
end
Expand All @@ -27,7 +27,7 @@ describe HTTP::DeflateHandler do
response = HTTP::Server::Response.new(io)
context = HTTP::Server::Context.new(request, response)

handler = HTTP::DeflateHandler.new
handler = HTTP::CompressHandler.new
handler.next = HTTP::Handler::Proc.new do |ctx|
ctx.response.print "Hello"
end
Expand All @@ -39,7 +39,7 @@ describe HTTP::DeflateHandler do
body = response2.body

io2 = IO::Memory.new
deflate = Zlib::Deflate.new(io2)
deflate = Flate::Writer.new(io2)
deflate.print "Hello"
deflate.close
io2.rewind
Expand All @@ -55,7 +55,7 @@ describe HTTP::DeflateHandler do
response = HTTP::Server::Response.new(io)
context = HTTP::Server::Context.new(request, response)

handler = HTTP::DeflateHandler.new
handler = HTTP::CompressHandler.new
handler.next = HTTP::Handler::Proc.new do |ctx|
ctx.response.print "Hello"
end
Expand All @@ -67,7 +67,7 @@ describe HTTP::DeflateHandler do
body = response2.body

io2 = IO::Memory.new
deflate = Zlib::Deflate.gzip(io2)
deflate = Gzip::Writer.new(io2)
deflate.print "Hello"
deflate.close
io2.rewind
Expand Down
4 changes: 2 additions & 2 deletions spec/std/http/server/server_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ module HTTP
server = Server.new("0.0.0.0", 0, [
ErrorHandler.new,
LogHandler.new,
DeflateHandler.new,
CompressHandler.new,
StaticFileHandler.new("."),
]
)
Expand All @@ -329,7 +329,7 @@ module HTTP
server = Server.new(0, [
ErrorHandler.new,
LogHandler.new,
DeflateHandler.new,
CompressHandler.new,
StaticFileHandler.new("."),
]
)
Expand Down
6 changes: 3 additions & 3 deletions spec/std/zip/zip_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ describe Zip do
io = IO::Memory.new

text = "contents of foo"
crc32 = Zlib.crc32(text)
crc32 = CRC32.checksum(text)

Zip::Writer.open(io) do |zip|
entry = Zip::Writer::Entry.new("foo.txt")
entry.compression_method = Zip::CompressionMethod::STORED
entry.crc32 = crc32.to_u32
entry.crc32 = crc32
entry.compressed_size = text.bytesize.to_u32
entry.uncompressed_size = text.bytesize.to_u32
zip.add entry, &.print(text)

entry = Zip::Writer::Entry.new("bar.txt")
entry.compression_method = Zip::CompressionMethod::STORED
entry.crc32 = crc32.to_u32
entry.crc32 = crc32
entry.compressed_size = text.bytesize.to_u32
entry.uncompressed_size = text.bytesize.to_u32
zip.add entry, &.print(text)
Expand Down
65 changes: 0 additions & 65 deletions spec/std/zlib/deflate_spec.cr

This file was deleted.

69 changes: 0 additions & 69 deletions spec/std/zlib/inflate_spec.cr

This file was deleted.

Loading

0 comments on commit bda40f8

Please sign in to comment.