streaming: create structure for packed object streams

As explained in a preceding commit, we want to get rid of the union of stream-type specific data in `struct odb_read_stream`. Create a new structure for packed object streams to move towards this design. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 23, 2025 at 19:59 UTC 5f0d8d2e8d3f992f58af247b6d21509c3c7595ca
1 file changed +40 -35
streaming.c
+40 -35
@@ -39,11 +39,6 @@ struct odb_read_stream {
39 enum { z_unused, z_used, z_done, z_error } z_state;
40
41 union {
42 - struct {
43 - struct packed_git *pack;
44 - off_t pos;
45 - } in_pack;
46 -
42 struct filtered_istream filtered;
43 } u;
44 };
@@ -287,16 +282,23 @@ error:
282 *
283 *****************************************************************/
284
290 -static ssize_t read_istream_pack_non_delta(struct odb_read_stream *st, char *buf,
285 +struct odb_packed_read_stream {
286 + struct odb_read_stream base;
287 + struct packed_git *pack;
288 + off_t pos;
289 +};
290 +
291 +static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *buf,
292 size_t sz)
293 {
294 + struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
295 size_t total_read = 0;
296
295 - switch (st->z_state) {
297 + switch (st->base.z_state) {
298 case z_unused:
297 - memset(&st->z, 0, sizeof(st->z));
298 - git_inflate_init(&st->z);
299 - st->z_state = z_used;
299 + memset(&st->base.z, 0, sizeof(st->base.z));
300 + git_inflate_init(&st->base.z);
301 + st->base.z_state = z_used;
302 break;
303 case z_done:
304 return 0;
@@ -311,21 +313,21 @@ static ssize_t read_istream_pack_non_delta(struct odb_read_stream *st, char *buf
313 struct pack_window *window = NULL;
314 unsigned char *mapped;
315
314 - mapped = use_pack(st->u.in_pack.pack, &window,
315 - st->u.in_pack.pos, &st->z.avail_in);
316 + mapped = use_pack(st->pack, &window,
317 + st->pos, &st->base.z.avail_in);
318
317 - st->z.next_out = (unsigned char *)buf + total_read;
318 - st->z.avail_out = sz - total_read;
319 - st->z.next_in = mapped;
320 - status = git_inflate(&st->z, Z_FINISH);
319 + st->base.z.next_out = (unsigned char *)buf + total_read;
320 + st->base.z.avail_out = sz - total_read;
321 + st->base.z.next_in = mapped;
322 + status = git_inflate(&st->base.z, Z_FINISH);
323
322 - st->u.in_pack.pos += st->z.next_in - mapped;
323 - total_read = st->z.next_out - (unsigned char *)buf;
324 + st->pos += st->base.z.next_in - mapped;
325 + total_read = st->base.z.next_out - (unsigned char *)buf;
326 unuse_pack(&window);
327
328 if (status == Z_STREAM_END) {
327 - git_inflate_end(&st->z);
328 - st->z_state = z_done;
329 + git_inflate_end(&st->base.z);
330 + st->base.z_state = z_done;
331 break;
332 }
333
@@ -338,17 +340,18 @@ static ssize_t read_istream_pack_non_delta(struct odb_read_stream *st, char *buf
340 * or truncated), then use_pack() catches that and will die().
341 */
342 if (status != Z_OK && status != Z_BUF_ERROR) {
341 - git_inflate_end(&st->z);
342 - st->z_state = z_error;
343 + git_inflate_end(&st->base.z);
344 + st->base.z_state = z_error;
345 return -1;
346 }
347 }
348 return total_read;
349 }
350
349 -static int close_istream_pack_non_delta(struct odb_read_stream *st)
351 +static int close_istream_pack_non_delta(struct odb_read_stream *_st)
352 {
351 - close_deflated_stream(st);
353 + struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
354 + close_deflated_stream(&st->base);
355 return 0;
356 }
357
@@ -358,19 +361,17 @@ static int open_istream_pack_non_delta(struct odb_read_stream **out,
361 struct packed_git *pack,
362 off_t offset)
363 {
361 - struct odb_read_stream stream = {
362 - .close = close_istream_pack_non_delta,
363 - .read = read_istream_pack_non_delta,
364 - };
364 + struct odb_packed_read_stream *stream;
365 struct pack_window *window;
366 enum object_type in_pack_type;
367 + size_t size;
368
369 window = NULL;
370
371 in_pack_type = unpack_object_header(pack,
372 &window,
373 &offset,
373 - &stream.size);
374 + &size);
375 unuse_pack(&window);
376 switch (in_pack_type) {
377 default:
@@ -381,13 +382,17 @@ static int open_istream_pack_non_delta(struct odb_read_stream **out,
382 case OBJ_TAG:
383 break;
384 }
384 - stream.type = in_pack_type;
385 - stream.z_state = z_unused;
386 - stream.u.in_pack.pack = pack;
387 - stream.u.in_pack.pos = offset;
385
389 - CALLOC_ARRAY(*out, 1);
390 - **out = stream;
386 + CALLOC_ARRAY(stream, 1);
387 + stream->base.close = close_istream_pack_non_delta;
388 + stream->base.read = read_istream_pack_non_delta;
389 + stream->base.type = in_pack_type;
390 + stream->base.size = size;
391 + stream->base.z_state = z_unused;
392 + stream->pack = pack;
393 + stream->pos = offset;
394 +
395 + *out = &stream->base;
396
397 return 0;
398 }