-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from lightpanda-io/wrapper
Wrapper
- Loading branch information
Showing
9 changed files
with
247 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,4 +31,3 @@ jobs: | |
fetch-depth: 0 | ||
|
||
- run: zig build test | ||
- run: zig build run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
const std = @import("std"); | ||
|
||
// Blocking is an example implementation of an IO API | ||
// following the zig-async-io model. | ||
// As it name suggests in this implementation all operations are | ||
// in fact blocking, the async API is just faked. | ||
pub const Blocking = @This(); | ||
|
||
pub const Completion = void; | ||
|
||
pub const ConnectError = std.posix.ConnectError; | ||
pub const SendError = std.posix.WriteError; | ||
pub const RecvError = std.posix.ReadError; | ||
|
||
pub fn connect( | ||
_: *Blocking, | ||
comptime CtxT: type, | ||
ctx: *CtxT, | ||
_: *Completion, | ||
comptime cbk: fn (ctx: *CtxT, _: *Completion, res: ConnectError!void) void, | ||
socket: std.posix.socket_t, | ||
address: std.net.Address, | ||
) void { | ||
std.posix.connect(socket, &address.any, address.getOsSockLen()) catch |err| { | ||
cbk(ctx, @constCast(&{}), err); | ||
return; | ||
}; | ||
cbk(ctx, @constCast(&{}), {}); | ||
} | ||
|
||
pub fn onConnect(_: *Blocking, _: ConnectError!void) void {} | ||
|
||
pub fn send( | ||
_: *Blocking, | ||
comptime CtxT: type, | ||
ctx: *CtxT, | ||
_: *Completion, | ||
comptime cbk: fn (ctx: *CtxT, _: *Completion, res: SendError!usize) void, | ||
socket: std.posix.socket_t, | ||
buf: []const u8, | ||
) void { | ||
const len = std.posix.write(socket, buf) catch |err| { | ||
cbk(ctx, @constCast(&{}), err); | ||
return; | ||
}; | ||
cbk(ctx, @constCast(&{}), len); | ||
} | ||
|
||
pub fn onSend(_: *Blocking, _: SendError!usize) void {} | ||
|
||
pub fn recv( | ||
_: *Blocking, | ||
comptime CtxT: type, | ||
ctx: *CtxT, | ||
_: *Completion, | ||
comptime cbk: fn (ctx: *CtxT, _: *Completion, res: RecvError!usize) void, | ||
socket: std.posix.socket_t, | ||
buf: []u8, | ||
) void { | ||
const len = std.posix.read(socket, buf) catch |err| { | ||
cbk(ctx, @constCast(&{}), err); | ||
return; | ||
}; | ||
cbk(ctx, @constCast(&{}), len); | ||
} | ||
|
||
pub fn onRecv(_: *Blocking, _: RecvError!usize) void {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,147 @@ | ||
const std = @import("std"); | ||
|
||
pub const Ctx = @import("std/http/Client.zig").Ctx; | ||
pub const Cbk = @import("std/http/Client.zig").Cbk; | ||
|
||
pub const Blocking = struct { | ||
pub fn connect( | ||
_: *Blocking, | ||
comptime ctxT: type, | ||
ctx: *ctxT, | ||
comptime cbk: Cbk, | ||
socket: std.posix.socket_t, | ||
address: std.net.Address, | ||
) void { | ||
std.posix.connect(socket, &address.any, address.getOsSockLen()) catch |err| { | ||
std.posix.close(socket); | ||
cbk(ctx, err) catch |e| { | ||
ctx.setErr(e); | ||
}; | ||
}; | ||
cbk(ctx, {}) catch |e| ctx.setErr(e); | ||
// IO is a type defined via a root declaration. | ||
// It must implements the following methods: | ||
// - connect, onConnect | ||
// - send, onSend | ||
// - recv, onRecv | ||
// It must also define the following types: | ||
// - Completion | ||
// - ConnectError | ||
// - SendError | ||
// - RecvError | ||
// see Blocking.io for an implementation example. | ||
pub const IO = blk: { | ||
const root = @import("root"); | ||
if (@hasDecl(root, "IO")) { | ||
break :blk root.IO; | ||
} | ||
@compileError("no IO API defined at root"); | ||
}; | ||
|
||
// Wrapper for a base IO API. | ||
pub fn Wrapper(IO_T: type) type { | ||
return struct { | ||
io: *IO_T, | ||
completion: IO_T.Completion, | ||
|
||
const Self = @This(); | ||
|
||
pub fn init(io: *IO_T) Self { | ||
return .{ .io = io, .completion = undefined }; | ||
} | ||
|
||
// NOTE: Business methods connect, send, recv expect a Ctx | ||
// who should reference the base IO API in Ctx.io field | ||
|
||
// NOTE: Ctx is already known (ie. @import("std/http/Client.zig").Ctx) | ||
// but we require to provide its type (comptime) as argument | ||
// to avoid dependency loop | ||
// ie. Wrapper requiring Ctx and Ctx requiring Wrapper | ||
|
||
fn Cbk(comptime Ctx: type) type { | ||
return *const fn (ctx: *Ctx, res: anyerror!void) anyerror!void; | ||
} | ||
|
||
pub fn send( | ||
_: *Blocking, | ||
comptime ctxT: type, | ||
ctx: *ctxT, | ||
comptime cbk: Cbk, | ||
socket: std.posix.socket_t, | ||
buf: []const u8, | ||
) void { | ||
const len = std.posix.write(socket, buf) catch |err| { | ||
cbk(ctx, err) catch |e| { | ||
return ctx.setErr(e); | ||
pub fn connect( | ||
self: *Self, | ||
comptime Ctx: type, | ||
ctx: *Ctx, | ||
comptime cbk: Cbk(Ctx), | ||
socket: std.posix.socket_t, | ||
address: std.net.Address, | ||
) void { | ||
self.io.connect(Ctx, ctx, &self.completion, onConnect(Ctx, cbk), socket, address); | ||
} | ||
|
||
fn onConnectFn(comptime Ctx: type) type { | ||
return fn ( | ||
ctx: *Ctx, | ||
_: *IO_T.Completion, | ||
result: IO_T.ConnectError!void, | ||
) void; | ||
} | ||
fn onConnect(comptime Ctx: type, comptime cbk: Cbk(Ctx)) onConnectFn(Ctx) { | ||
const s = struct { | ||
fn on( | ||
ctx: *Ctx, | ||
_: *IO_T.Completion, | ||
result: IO_T.ConnectError!void, | ||
) void { | ||
ctx.io.io.onConnect(result); // base IO callback | ||
_ = result catch |err| return ctx.setErr(err); | ||
cbk(ctx, {}) catch |err| return ctx.setErr(err); | ||
} | ||
}; | ||
return ctx.setErr(err); | ||
}; | ||
ctx.setLen(len); | ||
cbk(ctx, {}) catch |e| ctx.setErr(e); | ||
} | ||
return s.on; | ||
} | ||
|
||
pub fn recv( | ||
_: *Blocking, | ||
comptime ctxT: type, | ||
ctx: *ctxT, | ||
comptime cbk: Cbk, | ||
socket: std.posix.socket_t, | ||
buf: []u8, | ||
) void { | ||
const len = std.posix.read(socket, buf) catch |err| { | ||
cbk(ctx, err) catch |e| { | ||
return ctx.setErr(e); | ||
pub fn send( | ||
self: *Self, | ||
comptime Ctx: type, | ||
ctx: *Ctx, | ||
comptime cbk: Cbk(Ctx), | ||
socket: std.posix.socket_t, | ||
buf: []const u8, | ||
) void { | ||
self.io.send(Ctx, ctx, &self.completion, onSend(Ctx, cbk), socket, buf); | ||
} | ||
|
||
fn onSendFn(comptime Ctx: type) type { | ||
return fn ( | ||
ctx: *Ctx, | ||
_: *IO_T.Completion, | ||
result: IO_T.SendError!usize, | ||
) void; | ||
} | ||
fn onSend(comptime Ctx: type, comptime cbk: Cbk(Ctx)) onSendFn(Ctx) { | ||
const s = struct { | ||
fn on( | ||
ctx: *Ctx, | ||
_: *IO_T.Completion, | ||
result: IO_T.SendError!usize, | ||
) void { | ||
ctx.io.io.onSend(result); // base IO callback | ||
const len = result catch |err| return ctx.setErr(err); | ||
ctx.setLen(len); | ||
cbk(ctx, {}) catch |e| ctx.setErr(e); | ||
} | ||
}; | ||
return ctx.setErr(err); | ||
}; | ||
ctx.setLen(len); | ||
cbk(ctx, {}) catch |e| ctx.setErr(e); | ||
} | ||
}; | ||
return s.on; | ||
} | ||
|
||
pub fn recv( | ||
self: *Self, | ||
comptime Ctx: type, | ||
ctx: *Ctx, | ||
comptime cbk: Cbk(Ctx), | ||
socket: std.posix.socket_t, | ||
buf: []u8, | ||
) void { | ||
self.io.recv(Ctx, ctx, &self.completion, onRecv(Ctx, cbk), socket, buf); | ||
} | ||
|
||
fn onRecvFn(comptime Ctx: type) type { | ||
return fn ( | ||
ctx: *Ctx, | ||
_: *IO_T.Completion, | ||
result: IO_T.RecvError!usize, | ||
) void; | ||
} | ||
fn onRecv(comptime Ctx: type, comptime cbk: Cbk(Ctx)) onRecvFn(Ctx) { | ||
const s = struct { | ||
fn do( | ||
ctx: *Ctx, | ||
_: *IO_T.Completion, | ||
result: IO_T.RecvError!usize, | ||
) void { | ||
ctx.io.io.onRecv(result); // base IO callback | ||
const len = result catch |err| return ctx.setErr(err); | ||
ctx.setLen(len); | ||
cbk(ctx, {}) catch |err| return ctx.setErr(err); | ||
} | ||
}; | ||
return s.do; | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub const Wrapper = @import("io.zig").Wrapper; | ||
pub const Client = @import("std/http/Client.zig"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.