Track transferred bytes/progress of longer PUT request with std.http

You got the wrong userdata. Basically you are passing pointer to your own Writer interface, to the underlying writer which expects pointer to its own Writer interface. Should be

        const n = try self.inner.vtable.drain(self.inner, data, splat);

Otherwise looking good. Took me a while to spot the issue.

2 Likes

Hey, thank you very much. It totally makes sense, but is hard to get while reading through the source code.

It now works with this code:

pub const CountingWriter = struct {
    inner: *std.Io.Writer,
    pos: u64 = 0,
    interface: std.Io.Writer,

    pub fn init(inner: *std.Io.Writer, buffer: []u8) CountingWriter {
        return .{
            .inner = inner,
            .interface = .{
                .vtable = &.{
                    .drain = drainFn,
                },
                .buffer = buffer,
                .end = 0,
            },
        };
    }

    fn drainFn(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize {
        const self: *CountingWriter = @fieldParentPtr("interface", w);
        const n = try self.inner.vtable.drain(self.inner, data, splat);
        self.pos += n;
        std.debug.print("{d}\n", .{self.logicalPos()});
        return n;
    }

    pub fn logicalPos(self: *const CountingWriter) u64 {
        return self.pos;
    }
};

Thanks @psznm , @xeubie and @lalinsky for all the good examples and advices. I’ll mark this as solution, because its working code; so anyone who is looking to solve a similar task finds it. But of course, I would not have worked it out (this fast or maybe ever?) without help of the named users!!

1 Like

I took the inspirations and tipps from this thread and implemented wrapping Reader and Writer for the http requests of the S3 lib z3. I hope this is might help somebody who has a similar task to solve. And of course thanks again to anybody who answered in this thread!

1 Like