let unzip ?(format=`raw) ?(zlib_buffer_size=Default.zlib_buffer_size) () =
let zstream = ref (Zlib.inflate_init false) in
let in_buffer = Buffer.create 42 in
let zlib_write_buffer = String.create zlib_buffer_size in
dbg "unzip init: zlib_buffer_size: %d" zlib_buffer_size;
let current_state =
ref (match format with `gzip -> `gzip_header | `raw -> `inflate) in
let rec next stopped =
let buffered = Buffer.contents in_buffer in
let len = String.length buffered in
Buffer.clear in_buffer;
dbg "unzip: len: %d" len;
begin match len with
| 0 -> if stopped then `end_of_stream else `not_ready
| _ ->
begin match !current_state with
| `inflate ->
begin
try
let inflation =
inflate_as_much_as_possible in_buffer buffered
!zstream zlib_write_buffer zlib_buffer_size format in
begin match inflation with
| `output o -> `output o
| `error e -> `output (Error e)
| `not_ready -> `not_ready
| `finished_gzip out ->
current_state := `gzip_header;
zstream := Zlib.inflate_init false;
out
end
with
| e ->
dbg "E: %s; len: %d" (Exn.to_string e) len;
`output (Error (`zlib (Exn.to_string e)))
end
| `gzip_header ->
begin
try
match try_skip_gzip_header_exn buffered with
| Ok bytes_read ->
current_state := `inflate;
dbg "header bytes_read: %d" bytes_read;
Buffer.add_string in_buffer
String.(sub buffered bytes_read (len - bytes_read));
next stopped
| Error e -> `output (Error e)
with
e -> Buffer.add_string in_buffer buffered; `not_ready
end
end
end
in
Biocaml_transform.make_result ()
~feed:(fun string -> Buffer.add_string in_buffer string;) ~next