128 lines
4.1 KiB
Zig
128 lines
4.1 KiB
Zig
|
const std = @import("std");
|
||
|
const zzz = @import("zzz");
|
||
|
const _comptime = @import("utils/comptime.zig");
|
||
|
|
||
|
/// Type of a dispatcher run function.
|
||
|
pub fn DispatchFunction(AuthenticationType: type, PayloadType: type) type {
|
||
|
return *const fn(context: DispatcherContext(AuthenticationType, PayloadType)) void;
|
||
|
}
|
||
|
|
||
|
/// Model dispatcher runtime context structure.
|
||
|
pub fn DispatcherContext(AuthenticationType: type, PayloadType: type) type {
|
||
|
return struct {
|
||
|
/// Payload of the running dispatch.
|
||
|
payload: *const PayloadType,
|
||
|
|
||
|
/// The authenticated account, if there is one. NULL = no authenticated account.
|
||
|
account: ?*AuthenticationType,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/// Dispatcher builder interface.
|
||
|
pub const DispatcherBuilder = struct {
|
||
|
build: *const fn (comptime modelName: []const u8, comptime dispatchName: []const u8) Dispatcher,
|
||
|
};
|
||
|
|
||
|
/// Compile-time model dispatcher definition structure.
|
||
|
pub fn DispatcherDefinition(AuthenticationType: type, PayloadType: type) type {
|
||
|
return struct {
|
||
|
const Self = @This();
|
||
|
|
||
|
pub const Context = DispatcherContext(AuthenticationType, PayloadType);
|
||
|
pub const Policy = DispatcherPolicy(AuthenticationType, PayloadType);
|
||
|
pub const PolicyContext = DispatcherPolicyContext(AuthenticationType, PayloadType);
|
||
|
pub const Dispatch = DispatchFunction(AuthenticationType, PayloadType);
|
||
|
|
||
|
/// Dispatcher call policy.
|
||
|
policy: Policy,
|
||
|
/// Run function of the dispatcher.
|
||
|
run: Dispatch,
|
||
|
|
||
|
/// HTTP method to use in HTTP API for this dispatcher.
|
||
|
httpMethod: zzz.HTTP.Method = zzz.HTTP.Method.GET,
|
||
|
|
||
|
/// Initialize a dispatcher builder for the defined dispatcher.
|
||
|
pub fn builder(comptime self: *const Self) DispatcherBuilder {
|
||
|
return DispatcherBuilder{
|
||
|
.build = struct {
|
||
|
fn f(comptime modelName: []const u8, comptime dispatchName: []const u8) Dispatcher {
|
||
|
// Build the model identifier from the model name.
|
||
|
const modelIdentifier = comptime _comptime.pascalToKebab(modelName);
|
||
|
|
||
|
return Dispatcher{
|
||
|
._interface = .{
|
||
|
.instance = self,
|
||
|
|
||
|
.getModelIdentifier = struct { pub fn f(_: *const anyopaque) []const u8 {
|
||
|
return modelIdentifier;
|
||
|
} }.f,
|
||
|
|
||
|
.getDispatchName = struct { pub fn f(_: *const anyopaque) []const u8 {
|
||
|
return dispatchName;
|
||
|
} }.f,
|
||
|
|
||
|
.getHttpMethod = struct { pub fn f(opaqueSelf: *const anyopaque) zzz.HTTP.Method {
|
||
|
const impl: *const Self = @ptrCast(@alignCast(opaqueSelf));
|
||
|
return impl.httpMethod;
|
||
|
} }.f,
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
}.f,
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/// Compile-time model dispatcher policy definition structure.
|
||
|
pub fn DispatcherPolicy(AuthenticationType: type, PayloadType: type) type {
|
||
|
return union(enum) {
|
||
|
/// Allow / disallow any call to the dispatcher.
|
||
|
any: bool,
|
||
|
/// Allow calls to the dispatcher with any authenticated account.
|
||
|
anyAuthenticated: bool,
|
||
|
/// Allow calls to the dispatcher if the defined function returns true.
|
||
|
func: *const fn(context: DispatcherPolicyContext(AuthenticationType, PayloadType)) bool, //TODO define rules instead of func?
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/// Model dispatcher policy runtime context structure.
|
||
|
pub fn DispatcherPolicyContext(AuthenticationType: type, PayloadType: type) type {
|
||
|
return struct {
|
||
|
/// Payload of the running dispatch.
|
||
|
payload: *const PayloadType,
|
||
|
|
||
|
/// The authenticated account, if there is one. NULL = no authenticated account.
|
||
|
account: ?*AuthenticationType,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
/// Dispatcher interface.
|
||
|
pub const Dispatcher = struct {
|
||
|
const Self = @This();
|
||
|
|
||
|
_interface: struct {
|
||
|
instance: *const anyopaque,
|
||
|
|
||
|
getModelIdentifier: *const fn(instance: *const anyopaque) []const u8,
|
||
|
getDispatchName: *const fn(instance: *const anyopaque) []const u8,
|
||
|
getHttpMethod: *const fn(instance: *const anyopaque) zzz.HTTP.Method,
|
||
|
},
|
||
|
|
||
|
/// Get model identifier.
|
||
|
pub fn getModelIdentifier(self: *const Self) []const u8 {
|
||
|
return self._interface.getModelIdentifier(self._interface.instance);
|
||
|
}
|
||
|
|
||
|
/// Get dispatch name.
|
||
|
pub fn getDispatchName(self: *const Self) []const u8 {
|
||
|
return self._interface.getDispatchName(self._interface.instance);
|
||
|
}
|
||
|
|
||
|
/// Get HTTP API method.
|
||
|
pub fn getHttpMethod(self: *const Self) zzz.HTTP.Method {
|
||
|
return self._interface.getHttpMethod(self._interface.instance);
|
||
|
}
|
||
|
};
|