+static read_method_decl(loose)
+{
+ size_t total_read = 0;
+
+ switch (st->z_state) {
+ case z_done:
+ return 0;
+ case z_error:
+ return -1;
+ default:
+ break;
+ }
+
+ if (st->u.loose.hdr_used < st->u.loose.hdr_avail) {
+ size_t to_copy = st->u.loose.hdr_avail - st->u.loose.hdr_used;
+ if (sz < to_copy)
+ to_copy = sz;
+ memcpy(buf, st->u.loose.hdr + st->u.loose.hdr_used, to_copy);
+ st->u.loose.hdr_used += to_copy;
+ total_read += to_copy;
+ }
+
+ while (total_read < sz) {
+ int status;
+
+ st->z.next_out = (unsigned char *)buf + total_read;
+ st->z.avail_out = sz - total_read;
+ status = git_inflate(&st->z, Z_FINISH);
+
+ total_read = st->z.next_out - (unsigned char *)buf;
+
+ if (status == Z_STREAM_END) {
+ git_inflate_end(&st->z);
+ st->z_state = z_done;
+ break;
+ }
+ if (status != Z_OK && status != Z_BUF_ERROR) {
+ git_inflate_end(&st->z);
+ st->z_state = z_error;
+ return -1;
+ }
+ }
+ return total_read;
+}
+
+static close_method_decl(loose)
+{
+ close_deflated_stream(st);
+ munmap(st->u.loose.mapped, st->u.loose.mapsize);
+ return 0;
+}
+
+static struct stream_vtbl loose_vtbl = {
+ close_istream_loose,
+ read_istream_loose,
+};
+