1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-20 15:14:08 +00:00

refactored endpoint Binder/Bind/Bound/Interface ... namings

This commit is contained in:
renerocksai 2025-03-30 12:20:43 +02:00
parent 458d6ee071
commit b05004291e
2 changed files with 73 additions and 68 deletions

View file

@ -32,7 +32,6 @@ pub fn Create(comptime Context: type) type {
context: *Context = undefined, context: *Context = undefined,
gpa: Allocator = undefined, gpa: Allocator = undefined,
opts: AppOpts = undefined, opts: AppOpts = undefined,
// endpoints: std.StringArrayHashMapUnmanaged(*Endpoint.Interface) = .empty,
endpoints: std.ArrayListUnmanaged(*Endpoint.Interface) = .empty, endpoints: std.ArrayListUnmanaged(*Endpoint.Interface) = .empty,
there_can_be_only_one: bool = false, there_can_be_only_one: bool = false,
@ -61,64 +60,68 @@ pub fn Create(comptime Context: type) type {
path: []const u8, path: []const u8,
destroy: *const fn (*Interface, Allocator) void = undefined, destroy: *const fn (*Interface, Allocator) void = undefined,
}; };
pub fn Wrap(T: type) type { pub fn Bind(ArbitraryEndpoint: type) type {
return struct { return struct {
wrapped: *T, endpoint: *ArbitraryEndpoint,
interface: Interface, interface: Interface,
// tbh: unnecessary, since we have it in _static // tbh: unnecessary, since we have it in _static
app_context: *Context, app_context: *Context,
const Wrapped = @This(); const Bound = @This();
pub fn unwrap(interface: *Interface) *Wrapped { pub fn unwrap(interface: *Interface) *Bound {
const self: *Wrapped = @alignCast(@fieldParentPtr("interface", interface)); const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
return self; return self;
} }
pub fn destroy(interface: *Interface, allocator: Allocator) void { pub fn destroy(interface: *Interface, allocator: Allocator) void {
const self: *Wrapped = @alignCast(@fieldParentPtr("interface", interface)); const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
allocator.destroy(self); allocator.destroy(self);
} }
pub fn onRequestWrapped(interface: *Interface, r: Request) !void { pub fn onRequestInterface(interface: *Interface, r: Request) !void {
var self: *Wrapped = Wrapped.unwrap(interface); var self: *Bound = Bound.unwrap(interface);
var arena = try get_arena(); var arena = try get_arena();
try self.onRequest(arena.allocator(), self.app_context, r); try self.onRequest(arena.allocator(), self.app_context, r);
_ = arena.reset(.{ .retain_with_limit = _static.opts.arena_retain_capacity }); _ = arena.reset(.{ .retain_with_limit = _static.opts.arena_retain_capacity });
} }
pub fn onRequest(self: *Wrapped, arena: Allocator, app_context: *Context, r: Request) !void { pub fn onRequest(self: *Bound, arena: Allocator, app_context: *Context, r: Request) !void {
const ret = switch (r.methodAsEnum()) { const ret = switch (r.methodAsEnum()) {
.GET => self.wrapped.*.get(arena, app_context, r), .GET => self.endpoint.*.get(arena, app_context, r),
.POST => self.wrapped.*.post(arena, app_context, r), .POST => self.endpoint.*.post(arena, app_context, r),
.PUT => self.wrapped.*.put(arena, app_context, r), .PUT => self.endpoint.*.put(arena, app_context, r),
.DELETE => self.wrapped.*.delete(arena, app_context, r), .DELETE => self.endpoint.*.delete(arena, app_context, r),
.PATCH => self.wrapped.*.patch(arena, app_context, r), .PATCH => self.endpoint.*.patch(arena, app_context, r),
.OPTIONS => self.wrapped.*.options(arena, app_context, r), .OPTIONS => self.endpoint.*.options(arena, app_context, r),
else => error.UnsupportedHtmlRequestMethod, else => error.UnsupportedHtmlRequestMethod,
}; };
if (ret) { if (ret) {
// handled without error // handled without error
} else |err| { } else |err| {
switch (self.wrapped.*.error_strategy) { switch (self.endpoint.*.error_strategy) {
.raise => return err, .raise => return err,
.log_to_response => return r.sendError(err, if (@errorReturnTrace()) |t| t.* else null, 505), .log_to_response => return r.sendError(err, if (@errorReturnTrace()) |t| t.* else null, 505),
.log_to_console => zap.debug("Error in {} {s} : {}", .{ Wrapped, r.method orelse "(no method)", err }), .log_to_console => zap.debug(
"Error in {} {s} : {}",
.{ Bound, r.method orelse "(no method)", err },
),
} }
} }
} }
}; };
} }
pub fn init(T: type, value: *T) Endpoint.Wrap(T) { pub fn init(ArbitraryEndpoint: type, endpoint: *ArbitraryEndpoint) Endpoint.Bind(ArbitraryEndpoint) {
checkEndpointType(T); checkEndpointType(ArbitraryEndpoint);
const BoundEp = Endpoint.Bind(ArbitraryEndpoint);
return .{ return .{
.wrapped = value, .endpoint = endpoint,
.interface = .{ .interface = .{
.path = value.path, .path = endpoint.path,
.call = Endpoint.Wrap(T).onRequestWrapped, .call = BoundEp.onRequestInterface,
.destroy = Endpoint.Wrap(T).destroy, .destroy = BoundEp.destroy,
}, },
.app_context = _static.context, .app_context = _static.context,
}; };
@ -262,9 +265,9 @@ pub fn Create(comptime Context: type) type {
} }
const EndpointType = @typeInfo(@TypeOf(endpoint)).pointer.child; const EndpointType = @typeInfo(@TypeOf(endpoint)).pointer.child;
Endpoint.checkEndpointType(EndpointType); Endpoint.checkEndpointType(EndpointType);
const wrapper = try _static.gpa.create(Endpoint.Wrap(EndpointType)); const bound = try _static.gpa.create(Endpoint.Bind(EndpointType));
wrapper.* = Endpoint.init(EndpointType, endpoint); bound.* = Endpoint.init(EndpointType, endpoint);
try _static.endpoints.append(_static.gpa, &wrapper.interface); try _static.endpoints.append(_static.gpa, &bound.interface);
} }
pub fn listen(_: *App, l: ListenerSettings) !void { pub fn listen(_: *App, l: ListenerSettings) !void {
@ -284,9 +287,9 @@ pub fn Create(comptime Context: type) type {
fn onRequest(r: Request) !void { fn onRequest(r: Request) !void {
if (r.path) |p| { if (r.path) |p| {
for (_static.endpoints.items) |wrapper| { for (_static.endpoints.items) |interface| {
if (std.mem.startsWith(u8, p, wrapper.path)) { if (std.mem.startsWith(u8, p, interface.path)) {
return try wrapper.call(wrapper, r); return try interface.call(interface, r);
} }
} }
} }

View file

@ -106,66 +106,68 @@ pub fn checkEndpointType(T: type) void {
} }
} }
pub const Wrapper = struct { pub const Binder = struct {
pub const Interface = struct { pub const Interface = struct {
call: *const fn (*Interface, zap.Request) anyerror!void = undefined, call: *const fn (*Interface, zap.Request) anyerror!void = undefined,
path: []const u8, path: []const u8,
destroy: *const fn (allocator: std.mem.Allocator, *Interface) void = undefined, destroy: *const fn (*Interface, std.mem.Allocator) void = undefined,
}; };
pub fn Wrap(T: type) type { pub fn Bind(ArbitraryEndpoint: type) type {
return struct { return struct {
wrapped: *T, endpoint: *ArbitraryEndpoint,
wrapper: Interface, interface: Interface,
const Wrapped = @This(); const Bound = @This();
pub fn unwrap(wrapper: *Interface) *Wrapped { pub fn unwrap(interface: *Interface) *Bound {
const self: *Wrapped = @alignCast(@fieldParentPtr("wrapper", wrapper)); const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
return self; return self;
} }
pub fn destroy(allocator: std.mem.Allocator, wrapper: *Interface) void { pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
const self: *Wrapped = @alignCast(@fieldParentPtr("wrapper", wrapper)); const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
allocator.destroy(self); allocator.destroy(self);
} }
pub fn onRequestWrapped(wrapper: *Interface, r: zap.Request) !void { pub fn onRequestInterface(interface: *Interface, r: zap.Request) !void {
var self: *Wrapped = Wrapped.unwrap(wrapper); var self: *Bound = Bound.unwrap(interface);
try self.onRequest(r); try self.onRequest(r);
} }
pub fn onRequest(self: *Wrapped, r: zap.Request) !void { pub fn onRequest(self: *Bound, r: zap.Request) !void {
const ret = switch (r.methodAsEnum()) { const ret = switch (r.methodAsEnum()) {
.GET => self.wrapped.*.get(r), .GET => self.endpoint.*.get(r),
.POST => self.wrapped.*.post(r), .POST => self.endpoint.*.post(r),
.PUT => self.wrapped.*.put(r), .PUT => self.endpoint.*.put(r),
.DELETE => self.wrapped.*.delete(r), .DELETE => self.endpoint.*.delete(r),
.PATCH => self.wrapped.*.patch(r), .PATCH => self.endpoint.*.patch(r),
.OPTIONS => self.wrapped.*.options(r), .OPTIONS => self.endpoint.*.options(r),
else => error.UnsupportedHtmlRequestMethod, else => error.UnsupportedHtmlRequestMethod,
}; };
if (ret) { if (ret) {
// handled without error // handled without error
} else |err| { } else |err| {
switch (self.wrapped.*.error_strategy) { switch (self.endpoint.*.error_strategy) {
.raise => return err, .raise => return err,
.log_to_response => return r.sendError(err, if (@errorReturnTrace()) |t| t.* else null, 505), .log_to_response => return r.sendError(err, if (@errorReturnTrace()) |t| t.* else null, 505),
.log_to_console => zap.debug("Error in {} {s} : {}", .{ Wrapped, r.method orelse "(no method)", err }), .log_to_console => zap.debug("Error in {} {s} : {}", .{ Bound, r.method orelse "(no method)", err }),
} }
} }
} }
}; };
} }
pub fn init(T: type, value: *T) Wrapper.Wrap(T) { pub fn init(ArbitraryEndpoint: type, value: *ArbitraryEndpoint) Binder.Bind(ArbitraryEndpoint) {
checkEndpointType(T); checkEndpointType(ArbitraryEndpoint);
var ret: Wrapper.Wrap(T) = .{ const BoundEp = Binder.Bind(ArbitraryEndpoint);
.wrapped = value, return .{
.wrapper = .{ .path = value.path }, .endpoint = value,
.interface = .{
.path = value.path,
.call = BoundEp.onRequestInterface,
.destroy = BoundEp.destroy,
},
}; };
ret.wrapper.call = Wrapper.Wrap(T).onRequestWrapped;
ret.wrapper.destroy = Wrapper.Wrap(T).destroy;
return ret;
} }
}; };
@ -262,7 +264,7 @@ pub const Listener = struct {
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
/// Internal static interface struct of member endpoints /// Internal static interface struct of member endpoints
var endpoints: std.ArrayListUnmanaged(*Wrapper.Interface) = .empty; var endpoints: std.ArrayListUnmanaged(*Binder.Interface) = .empty;
/// Internal, static request handler callback. Will be set to the optional, /// Internal, static request handler callback. Will be set to the optional,
/// user-defined request callback that only gets called if no endpoints match /// user-defined request callback that only gets called if no endpoints match
@ -296,8 +298,8 @@ pub const Listener = struct {
/// Registered endpoints will not be de-initialized automatically; just removed /// Registered endpoints will not be de-initialized automatically; just removed
/// from the internal map. /// from the internal map.
pub fn deinit(self: *Listener) void { pub fn deinit(self: *Listener) void {
for (endpoints.items) |endpoint_wrapper| { for (endpoints.items) |interface| {
endpoint_wrapper.destroy(self.allocator, endpoint_wrapper); interface.destroy(interface, self.allocator);
} }
endpoints.deinit(self.allocator); endpoints.deinit(self.allocator);
} }
@ -328,16 +330,16 @@ pub const Listener = struct {
} }
const EndpointType = @typeInfo(@TypeOf(e)).pointer.child; const EndpointType = @typeInfo(@TypeOf(e)).pointer.child;
checkEndpointType(EndpointType); checkEndpointType(EndpointType);
const wrapper = try self.allocator.create(Wrapper.Wrap(EndpointType)); const bound = try self.allocator.create(Binder.Bind(EndpointType));
wrapper.* = Wrapper.init(EndpointType, e); bound.* = Binder.init(EndpointType, e);
try endpoints.append(self.allocator, &wrapper.wrapper); try endpoints.append(self.allocator, &bound.interface);
} }
fn onRequest(r: Request) !void { fn onRequest(r: Request) !void {
if (r.path) |p| { if (r.path) |p| {
for (endpoints.items) |wrapper| { for (endpoints.items) |interface| {
if (std.mem.startsWith(u8, p, wrapper.path)) { if (std.mem.startsWith(u8, p, interface.path)) {
return try wrapper.call(wrapper, r); return try interface.call(interface, r);
} }
} }
} }