start to abstract the decoding/encoding part. create modules for compression algorithms
This commit is contained in:
@@ -16,14 +16,28 @@ defmodule Dotzip do
|
||||
decode(data)
|
||||
end
|
||||
|
||||
|
||||
def encode(_data) do
|
||||
def encode(data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def encode_file(_file) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def end_central_directory?(<<signature::binary-size(4), _::bitstring>>) do
|
||||
end_central_directory = Dotzip.EndCentralDirectory.signature()
|
||||
signature == end_central_directory
|
||||
end
|
||||
|
||||
def central_directory_header?(<<signature::binary-size(4), _::bitstring>>) do
|
||||
central_directory_header = Dotzip.CentralDirectoryHeader.signature()
|
||||
signature == central_directory_header
|
||||
end
|
||||
|
||||
def local_file_header?(<<signature::binary-size(4), _::bitstring>>) do
|
||||
local_file_header = Dotzip.LocalFileHeader.signature()
|
||||
signature == local_file_header
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
defmodule Dotzip.CentralDirectoryHeader do
|
||||
|
||||
defp signature() do
|
||||
def signature() do
|
||||
<< 0x50, 0x4b, 0x01, 0x02 >>
|
||||
end
|
||||
|
||||
|
||||
9
lib/dotzip/compression/bzip2.ex
Normal file
9
lib/dotzip/compression/bzip2.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Bzip2 do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/deflating.ex
Normal file
9
lib/dotzip/compression/deflating.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Deflating do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/enhanced_deflating.ex
Normal file
9
lib/dotzip/compression/enhanced_deflating.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.EnhancedDeflating do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/expanding.ex
Normal file
9
lib/dotzip/compression/expanding.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Expanding do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/imploding.ex
Normal file
9
lib/dotzip/compression/imploding.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Imploding do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/lzma.ex
Normal file
9
lib/dotzip/compression/lzma.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Lzma do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/ppmd.ex
Normal file
9
lib/dotzip/compression/ppmd.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Ppmd do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/unshrinking.ex
Normal file
9
lib/dotzip/compression/unshrinking.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Unshrinking do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
9
lib/dotzip/compression/wavpack.ex
Normal file
9
lib/dotzip/compression/wavpack.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Dotzip.Compression.Wavpack do
|
||||
def compress(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
|
||||
def decompression(_data) do
|
||||
{:error, :not_supported}
|
||||
end
|
||||
end
|
||||
@@ -1,42 +1,82 @@
|
||||
defmodule Dotzip.EndCentralDirectory do
|
||||
|
||||
def signature() do
|
||||
<< 0x50, 0x4b, 0x05, 0x06 >>
|
||||
end
|
||||
|
||||
defp signature(<< 0x50, 0x4b, 0x05, 0x06, rest::bitstring >>) do
|
||||
{:ok, %{}, rest}
|
||||
end
|
||||
|
||||
defp encode_signature(data) when is_map(data) do
|
||||
{:ok, data, signature()}
|
||||
end
|
||||
|
||||
defp number_disk({:ok, data, << number_disk::little-size(16), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :number_disk, number_disk), rest}
|
||||
end
|
||||
|
||||
defp encode_number_disk({:ok, %{ :number_disk => number_disk } = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, number_disk::little-size(16)>>}
|
||||
end
|
||||
|
||||
defp number_disk_start({:ok, data, << number_disk::little-size(16), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :number_disk_start, number_disk), rest}
|
||||
end
|
||||
|
||||
defp encode_number_disk_start({:ok, %{ :number_disk_start => number_disk_start } = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, number_disk_start::little-size(16)>> }
|
||||
end
|
||||
|
||||
defp total_entries_disk({:ok, data, << total_entries_disk::little-size(16), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :total_entries_disk, total_entries_disk), rest}
|
||||
end
|
||||
|
||||
defp encode_total_entries_disk({:ok, %{ :total_entries_disk => total_entries_disk } = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, total_entries_disk::little-size(16)>> }
|
||||
end
|
||||
|
||||
defp total_entries({:ok, data, << total_entries::little-size(16), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :total_entries, total_entries), rest}
|
||||
end
|
||||
|
||||
defp encode_total_entries({:ok, %{ :total_entries => total_entries } = data, buffer }) do
|
||||
{:ok, data, <<buffer::bitstring, total_entries::little-size(16)>> }
|
||||
end
|
||||
|
||||
defp size({:ok, data, << size::little-size(32), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :size, size), rest}
|
||||
end
|
||||
|
||||
defp encode_size({:ok, %{ :size => size } = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, size::little-size(32)>>}
|
||||
end
|
||||
|
||||
defp offset({:ok, data, << offset::little-size(32), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :offset, offset), rest}
|
||||
end
|
||||
|
||||
defp encode_offset({:ok, %{ :offset => offset } = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, offset::little-size(32)>> }
|
||||
end
|
||||
|
||||
defp comment_length({:ok, data, << comment_length::little-size(16), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :comment_length, comment_length), rest}
|
||||
end
|
||||
|
||||
defp encode_comment_length({:ok, %{ :comment_length => comment_length } = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, comment_length::little-size(16)>> }
|
||||
end
|
||||
|
||||
defp comment({:ok, data, rest}) do
|
||||
%{ :comment_length => comment_length } = data
|
||||
<< comment::binary-size(comment_length), r::bitstring >> = rest
|
||||
{:ok, Map.put(data, :comment, comment), r}
|
||||
end
|
||||
|
||||
defp encode_comment({:ok, %{ :comment => comment, :comment_length => comment_length} = data, buffer}) do
|
||||
{:ok, data, <<buffer::bitstring, comment::binary-size(comment_length)>>}
|
||||
end
|
||||
|
||||
def decode(file) do
|
||||
{:ok, end_central_directory, rest} = signature(file)
|
||||
@@ -49,5 +89,17 @@ defmodule Dotzip.EndCentralDirectory do
|
||||
|> comment_length()
|
||||
|> comment()
|
||||
end
|
||||
|
||||
def encode(data) do
|
||||
encode_signature(data)
|
||||
|> encode_number_disk()
|
||||
|> encode_number_disk_start()
|
||||
|> encode_total_entries_disk()
|
||||
|> encode_total_entries()
|
||||
|> encode_size()
|
||||
|> encode_offset()
|
||||
|> encode_comment_length()
|
||||
|> encode_comment()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
13
lib/dotzip/format.ex
Normal file
13
lib/dotzip/format.ex
Normal file
@@ -0,0 +1,13 @@
|
||||
# https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime?redirectedfrom=MSDN
|
||||
|
||||
defmodule Dotzip.Format.Msdos do
|
||||
|
||||
def decode_date(<<day::size(5), month::size(4), offset::size(7)>>) do
|
||||
Date.new(1980+offset, month, day)
|
||||
end
|
||||
|
||||
def decode_time(<<second::size(5), minute::size(6), hour::size(5)>>) do
|
||||
Time.new(hour, minute, second*2, 0)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
defmodule Dotzip.LocalFileHeader do
|
||||
|
||||
defp signature() do
|
||||
def signature() do
|
||||
<< 0x50, 0x4b, 0x03, 0x04 >>
|
||||
end
|
||||
|
||||
@@ -23,13 +23,41 @@ defmodule Dotzip.LocalFileHeader do
|
||||
defp purpose_flag({:ok, data, << purpose_flag::binary-size(2), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :purpose_flag, purpose_flag), rest}
|
||||
end
|
||||
|
||||
|
||||
defp encode_purpose_flag({:ok, %{ :purpose_flag => purpose_flag } = data, buffer }) do
|
||||
{:ok, data, <<buffer::bitstring, purpose_flag::binary-size(2)>> }
|
||||
end
|
||||
|
||||
defp compression_method({:ok, data, << compression_method::binary-size(2), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :compression_method, compression_method), rest}
|
||||
defp compression_method_type(data) do
|
||||
case data do
|
||||
0 -> :stored
|
||||
1 -> :shrunk
|
||||
2 -> :reduced_factor1
|
||||
3 -> :reduced_factor2
|
||||
4 -> :reduced_factor3
|
||||
5 -> :reduced_factor4
|
||||
6 -> :imploded
|
||||
7 -> :tokenizing
|
||||
8 -> :deflated
|
||||
9 -> :deflate64
|
||||
10 -> :pkware
|
||||
11 -> :reserved
|
||||
12 -> :bzip2
|
||||
13 -> :reserved
|
||||
14 -> :lzma
|
||||
15 -> :reserved
|
||||
16 -> :reserved
|
||||
17 -> :reserved
|
||||
18 -> :terse
|
||||
19 -> :lz77
|
||||
97 -> :wavpack
|
||||
98 -> :ppmd
|
||||
end
|
||||
end
|
||||
|
||||
defp compression_method({:ok, data, << compression_method::little-size(16), rest::bitstring >>}) do
|
||||
method = compression_method_type(compression_method)
|
||||
{:ok, Map.put(data, :compression_method, method), rest}
|
||||
end
|
||||
|
||||
defp encode_compression_method({:ok, %{ :compression_method => compression_method } = data, buffer}) do
|
||||
@@ -44,7 +72,7 @@ defmodule Dotzip.LocalFileHeader do
|
||||
{:ok, data, <<buffer::bitstring, last_modification_time::little-size(16)>>}
|
||||
end
|
||||
|
||||
defp last_modification_date({:ok, data, << last_modification_date::little-size(16), rest::bitstring >>}) do
|
||||
defp last_modification_date({:ok, data, << last_modification_date::little-binary-size(2), rest::bitstring >>}) do
|
||||
{:ok, Map.put(data, :last_modification_date, last_modification_date), rest}
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user