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:
parent
458d6ee071
commit
b05004291e
2 changed files with 73 additions and 68 deletions
63
src/App.zig
63
src/App.zig
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue