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,
gpa: Allocator = undefined,
opts: AppOpts = undefined,
// endpoints: std.StringArrayHashMapUnmanaged(*Endpoint.Interface) = .empty,
endpoints: std.ArrayListUnmanaged(*Endpoint.Interface) = .empty,
there_can_be_only_one: bool = false,
@ -61,64 +60,68 @@ pub fn Create(comptime Context: type) type {
path: []const u8,
destroy: *const fn (*Interface, Allocator) void = undefined,
};
pub fn Wrap(T: type) type {
pub fn Bind(ArbitraryEndpoint: type) type {
return struct {
wrapped: *T,
endpoint: *ArbitraryEndpoint,
interface: Interface,
// tbh: unnecessary, since we have it in _static
app_context: *Context,
const Wrapped = @This();
const Bound = @This();
pub fn unwrap(interface: *Interface) *Wrapped {
const self: *Wrapped = @alignCast(@fieldParentPtr("interface", interface));
pub fn unwrap(interface: *Interface) *Bound {
const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
return self;
}
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);
}
pub fn onRequestWrapped(interface: *Interface, r: Request) !void {
var self: *Wrapped = Wrapped.unwrap(interface);
pub fn onRequestInterface(interface: *Interface, r: Request) !void {
var self: *Bound = Bound.unwrap(interface);
var arena = try get_arena();
try self.onRequest(arena.allocator(), self.app_context, r);
_ = 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()) {
.GET => self.wrapped.*.get(arena, app_context, r),
.POST => self.wrapped.*.post(arena, app_context, r),
.PUT => self.wrapped.*.put(arena, app_context, r),
.DELETE => self.wrapped.*.delete(arena, app_context, r),
.PATCH => self.wrapped.*.patch(arena, app_context, r),
.OPTIONS => self.wrapped.*.options(arena, app_context, r),
.GET => self.endpoint.*.get(arena, app_context, r),
.POST => self.endpoint.*.post(arena, app_context, r),
.PUT => self.endpoint.*.put(arena, app_context, r),
.DELETE => self.endpoint.*.delete(arena, app_context, r),
.PATCH => self.endpoint.*.patch(arena, app_context, r),
.OPTIONS => self.endpoint.*.options(arena, app_context, r),
else => error.UnsupportedHtmlRequestMethod,
};
if (ret) {
// handled without error
} else |err| {
switch (self.wrapped.*.error_strategy) {
switch (self.endpoint.*.error_strategy) {
.raise => return err,
.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) {
checkEndpointType(T);
pub fn init(ArbitraryEndpoint: type, endpoint: *ArbitraryEndpoint) Endpoint.Bind(ArbitraryEndpoint) {
checkEndpointType(ArbitraryEndpoint);
const BoundEp = Endpoint.Bind(ArbitraryEndpoint);
return .{
.wrapped = value,
.endpoint = endpoint,
.interface = .{
.path = value.path,
.call = Endpoint.Wrap(T).onRequestWrapped,
.destroy = Endpoint.Wrap(T).destroy,
.path = endpoint.path,
.call = BoundEp.onRequestInterface,
.destroy = BoundEp.destroy,
},
.app_context = _static.context,
};
@ -262,9 +265,9 @@ pub fn Create(comptime Context: type) type {
}
const EndpointType = @typeInfo(@TypeOf(endpoint)).pointer.child;
Endpoint.checkEndpointType(EndpointType);
const wrapper = try _static.gpa.create(Endpoint.Wrap(EndpointType));
wrapper.* = Endpoint.init(EndpointType, endpoint);
try _static.endpoints.append(_static.gpa, &wrapper.interface);
const bound = try _static.gpa.create(Endpoint.Bind(EndpointType));
bound.* = Endpoint.init(EndpointType, endpoint);
try _static.endpoints.append(_static.gpa, &bound.interface);
}
pub fn listen(_: *App, l: ListenerSettings) !void {
@ -284,9 +287,9 @@ pub fn Create(comptime Context: type) type {
fn onRequest(r: Request) !void {
if (r.path) |p| {
for (_static.endpoints.items) |wrapper| {
if (std.mem.startsWith(u8, p, wrapper.path)) {
return try wrapper.call(wrapper, r);
for (_static.endpoints.items) |interface| {
if (std.mem.startsWith(u8, p, interface.path)) {
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 {
call: *const fn (*Interface, zap.Request) anyerror!void = undefined,
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 {
wrapped: *T,
wrapper: Interface,
endpoint: *ArbitraryEndpoint,
interface: Interface,
const Wrapped = @This();
const Bound = @This();
pub fn unwrap(wrapper: *Interface) *Wrapped {
const self: *Wrapped = @alignCast(@fieldParentPtr("wrapper", wrapper));
pub fn unwrap(interface: *Interface) *Bound {
const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
return self;
}
pub fn destroy(allocator: std.mem.Allocator, wrapper: *Interface) void {
const self: *Wrapped = @alignCast(@fieldParentPtr("wrapper", wrapper));
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
const self: *Bound = @alignCast(@fieldParentPtr("interface", interface));
allocator.destroy(self);
}
pub fn onRequestWrapped(wrapper: *Interface, r: zap.Request) !void {
var self: *Wrapped = Wrapped.unwrap(wrapper);
pub fn onRequestInterface(interface: *Interface, r: zap.Request) !void {
var self: *Bound = Bound.unwrap(interface);
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()) {
.GET => self.wrapped.*.get(r),
.POST => self.wrapped.*.post(r),
.PUT => self.wrapped.*.put(r),
.DELETE => self.wrapped.*.delete(r),
.PATCH => self.wrapped.*.patch(r),
.OPTIONS => self.wrapped.*.options(r),
.GET => self.endpoint.*.get(r),
.POST => self.endpoint.*.post(r),
.PUT => self.endpoint.*.put(r),
.DELETE => self.endpoint.*.delete(r),
.PATCH => self.endpoint.*.patch(r),
.OPTIONS => self.endpoint.*.options(r),
else => error.UnsupportedHtmlRequestMethod,
};
if (ret) {
// handled without error
} else |err| {
switch (self.wrapped.*.error_strategy) {
switch (self.endpoint.*.error_strategy) {
.raise => return err,
.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) {
checkEndpointType(T);
var ret: Wrapper.Wrap(T) = .{
.wrapped = value,
.wrapper = .{ .path = value.path },
pub fn init(ArbitraryEndpoint: type, value: *ArbitraryEndpoint) Binder.Bind(ArbitraryEndpoint) {
checkEndpointType(ArbitraryEndpoint);
const BoundEp = Binder.Bind(ArbitraryEndpoint);
return .{
.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,
/// 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,
/// 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
/// from the internal map.
pub fn deinit(self: *Listener) void {
for (endpoints.items) |endpoint_wrapper| {
endpoint_wrapper.destroy(self.allocator, endpoint_wrapper);
for (endpoints.items) |interface| {
interface.destroy(interface, self.allocator);
}
endpoints.deinit(self.allocator);
}
@ -328,16 +330,16 @@ pub const Listener = struct {
}
const EndpointType = @typeInfo(@TypeOf(e)).pointer.child;
checkEndpointType(EndpointType);
const wrapper = try self.allocator.create(Wrapper.Wrap(EndpointType));
wrapper.* = Wrapper.init(EndpointType, e);
try endpoints.append(self.allocator, &wrapper.wrapper);
const bound = try self.allocator.create(Binder.Bind(EndpointType));
bound.* = Binder.init(EndpointType, e);
try endpoints.append(self.allocator, &bound.interface);
}
fn onRequest(r: Request) !void {
if (r.path) |p| {
for (endpoints.items) |wrapper| {
if (std.mem.startsWith(u8, p, wrapper.path)) {
return try wrapper.call(wrapper, r);
for (endpoints.items) |interface| {
if (std.mem.startsWith(u8, p, interface.path)) {
return try interface.call(interface, r);
}
}
}