11const std = @import ("std" );
22const errors = @import ("errors.zig" );
33const util = @import ("util.zig" );
4+ const types = @import ("types.zig" );
45const c = util .c ;
56
67const mem = std .mem ;
78const fmt = std .fmt ;
9+ const AnyWriter = std .io .AnyWriter ;
810const Allocator = mem .Allocator ;
911const checkCode = errors .checkCode ;
10- const ResizableBuffer = util .ResizableBuffer ;
12+ const ResizableBuffer = types .ResizableBuffer ;
1113
1214const hasParseHeaderSupport = @import ("util.zig" ).hasParseHeaderSupport ;
1315
@@ -52,6 +54,7 @@ pub const FetchOptions = struct {
5254 method : Method = .GET ,
5355 body : ? []const u8 = null ,
5456 headers : ? []const [:0 ]const u8 = null ,
57+ response_writer : ? AnyWriter = null ,
5558};
5659
5760pub const Response = struct {
@@ -338,11 +341,11 @@ pub fn setUnixSocketPath(self: Self, path: [:0]const u8) !void {
338341 try checkCode (c .curl_easy_setopt (self .handle , c .CURLOPT_UNIX_SOCKET_PATH , path .ptr ));
339342}
340343
341- pub fn setPrivate (self : Self , data : * anyopaque ) ! void {
344+ pub fn setPrivate (self : Self , data : * const anyopaque ) ! void {
342345 try checkCode (c .curl_easy_setopt (self .handle , c .CURLOPT_PRIVATE , data ));
343346}
344347
345- pub fn setWritedata (self : Self , data : * anyopaque ) ! void {
348+ pub fn setWritedata (self : Self , data : * const anyopaque ) ! void {
346349 try checkCode (c .curl_easy_setopt (self .handle , c .CURLOPT_WRITEDATA , data ));
347350}
348351
@@ -360,19 +363,21 @@ pub fn setWritefunction(
360363 try checkCode (c .curl_easy_setopt (self .handle , c .CURLOPT_WRITEFUNCTION , func ));
361364}
362365
363- /// Set `WRITEDATA` to context and `WRITEFUNCTION` to a function that calls with the context .
364- pub fn setWriteContext (
366+ /// Set `WRITEDATA` to AnyWriter and `WRITEFUNCTION` to a function that calls with the writer .
367+ pub fn setAnyWriter (
365368 self : Self ,
366- context : anytype ,
367- comptime writeFunc : fn (@TypeOf (context ), ptr : []const u8 ) usize ,
369+ any_writer : * const AnyWriter ,
368370) ! void {
369- try self .setWritedata (context );
371+ try self .setWritedata (any_writer );
370372 try self .setWritefunction (struct {
371373 fn write (ptr : [* c ]c_char , size : c_uint , nmemb : c_uint , user_data : * anyopaque ) callconv (.C ) c_uint {
372374 const real_size = size * nmemb ;
373- const ctx : @TypeOf (context ) = @alignCast (@ptrCast (user_data ));
374375 const data = (@as ([* ]const u8 , @ptrCast (ptr )))[0.. real_size ];
375- return @intCast (writeFunc (ctx , data ));
376+ const writer : * const AnyWriter = @alignCast (@ptrCast (user_data ));
377+ const ret = writer .write (data ) catch {
378+ return 0 ; // Indicate an error
379+ };
380+ return @intCast (ret );
376381 }
377382 }.write );
378383}
@@ -426,25 +431,6 @@ pub fn perform(self: Self) !Response {
426431 };
427432}
428433
429- fn setWriteContextInner (self : Self , context : anytype ) ! void {
430- const ctxType = @typeInfo (@TypeOf (context ));
431- switch (ctxType ) {
432- .void = > {
433- // No write context, do nothing.
434- return ;
435- },
436- .pointer = > | ptr | {
437- if (comptime ! @hasDecl (ptr .child , "write" )) {
438- @compileError ("writeContext must have a `write` function" );
439- }
440- try self .setWriteContext (context , @field (ptr .child , "write" ));
441- },
442- else = > {
443- @compileError ("writeContext must be a pointer or void type, current: " ++ @typeName (@TypeOf (context )));
444- },
445- }
446- }
447-
448434/// Head issues a HEAD to the specified URL.
449435pub fn head (self : Self , url : [:0 ]const u8 ) ! Response {
450436 try self .setUrl (url );
@@ -463,7 +449,6 @@ pub fn fetch(
463449 self : Self ,
464450 url : [:0 ]const u8 ,
465451 options : FetchOptions ,
466- writeContext : anytype ,
467452) ! Response {
468453 try self .setUrl (url );
469454 try self .setMethod (options .method );
@@ -483,20 +468,22 @@ pub fn fetch(
483468 h .deinit ();
484469 };
485470
486- try self .setWriteContextInner (writeContext );
471+ if (options .response_writer ) | writer | {
472+ try self .setAnyWriter (& writer );
473+ }
487474
488475 return try self .perform ();
489476}
490477
491478/// Upload issues a PUT request to upload file.
492479/// `writeContext` is the same as in `fetch`, used to write the response body.
493- pub fn upload (self : Self , url : [:0 ]const u8 , path : []const u8 , writeContext : anytype ) ! Response {
480+ pub fn upload (self : Self , url : [:0 ]const u8 , path : []const u8 , any_writer : AnyWriter ) ! Response {
494481 var up = try Upload .init (path );
495482 defer up .deinit ();
496483 try self .setUpload (& up );
497484
498485 try self .setUrl (url );
499- try self .setWriteContextInner ( writeContext );
486+ try self .setAnyWriter ( & any_writer );
500487 return try self .perform ();
501488}
502489
0 commit comments