Application Context Implementation #4
|
@ -69,7 +69,7 @@ pub const Allocator = union (enum) {
|
||||||
/// Closure that captures a reference to readable resources like block devices, memory buffers,
|
/// Closure that captures a reference to readable resources like block devices, memory buffers,
|
||||||
/// network sockets, and more.
|
/// network sockets, and more.
|
||||||
///
|
///
|
||||||
pub const Reader = meta.Function(@sizeOf(usize), []u8, usize);
|
pub const Reader = meta.Function([]u8, usize);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns a state machine for lazily computing all `Element` components of a given source input
|
/// Returns a state machine for lazily computing all `Element` components of a given source input
|
||||||
|
@ -187,7 +187,7 @@ test "Spliterator of string literals" {
|
||||||
/// Closure that captures a reference to writable resources like block devices, memory buffers,
|
/// Closure that captures a reference to writable resources like block devices, memory buffers,
|
||||||
/// network sockets, and more.
|
/// network sockets, and more.
|
||||||
///
|
///
|
||||||
pub const Writer = meta.Function(@sizeOf(usize), []const u8, usize);
|
pub const Writer = meta.Function([]const u8, usize);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns a sliced reference of the raw bytes in `pointer`.
|
/// Returns a sliced reference of the raw bytes in `pointer`.
|
||||||
|
@ -383,8 +383,10 @@ test "Data swapping" {
|
||||||
/// sent somewhere for whatever reason.
|
/// sent somewhere for whatever reason.
|
||||||
///
|
///
|
||||||
pub fn nullWriter() Writer {
|
pub fn nullWriter() Writer {
|
||||||
return Writer.capture(@as(usize, 0), struct {
|
var dummy: usize = 0;
|
||||||
fn write(_: usize, buffer: []const u8) usize {
|
|
||||||
|
return Writer.capture(&dummy, struct {
|
||||||
|
fn write(_: *usize, buffer: []const u8) usize {
|
||||||
return buffer.len;
|
return buffer.len;
|
||||||
}
|
}
|
||||||
}.write);
|
}.write);
|
||||||
|
|
|
@ -13,10 +13,10 @@ pub fn FnReturn(comptime Fn: type) type {
|
||||||
/// Returns a single-input single-output closure type where `In` represents the input type, `Out`
|
/// Returns a single-input single-output closure type where `In` represents the input type, `Out`
|
||||||
/// represents the output type, and `captures_size` represents the size of the closure context.
|
/// represents the output type, and `captures_size` represents the size of the closure context.
|
||||||
///
|
///
|
||||||
pub fn Function(comptime captures_size: usize, comptime In: type, comptime Out: type) type {
|
pub fn Function(comptime In: type, comptime Out: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
callErased: fn (*anyopaque, In) Out,
|
callErased: fn (*anyopaque, In) Out,
|
||||||
context: [captures_size]u8,
|
context: *anyopaque,
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Function type.
|
/// Function type.
|
||||||
|
@ -27,37 +27,36 @@ pub fn Function(comptime captures_size: usize, comptime In: type, comptime Out:
|
||||||
/// Invokes `self` with `input`, producing a result according to the current context data.
|
/// Invokes `self` with `input`, producing a result according to the current context data.
|
||||||
///
|
///
|
||||||
pub fn call(self: *Self, input: In) Out {
|
pub fn call(self: *Self, input: In) Out {
|
||||||
return self.callErased(&self.context, input);
|
return self.callErased(self.context, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Creates a new [Self] by capturing the `captures` value as the context and `invoke` as
|
/// Creates a new [Self] by capturing the `context` value as the capture context and
|
||||||
/// the as the behavior executed when [call] or [callErased] is called.
|
/// `invoke` as the behavior executed when [call] or [callErased] is called.
|
||||||
///
|
///
|
||||||
/// The newly created [Self] is returned.
|
/// The newly created [Self] is returned.
|
||||||
///
|
///
|
||||||
pub fn capture(captures: anytype, comptime invoke: fn (@TypeOf(captures), In) Out) Self {
|
pub fn capture(context: anytype, comptime invoke: fn (@TypeOf(context), In) Out) Self {
|
||||||
const Captures = @TypeOf(captures);
|
const Context = @TypeOf(context);
|
||||||
|
|
||||||
if (@sizeOf(Captures) > captures_size)
|
switch (@typeInfo(Context)) {
|
||||||
@compileError("`captures` exceeds the size limit of the capture context");
|
.Pointer => |info| if (info.size == .Slice)
|
||||||
|
@compileError("`context` cannot be a slice"),
|
||||||
|
|
||||||
const captures_align = @alignOf(Captures);
|
else => @compileError("`context` must be a pointer"),
|
||||||
|
}
|
||||||
|
|
||||||
var function = Self{
|
var function = Self{
|
||||||
.context = undefined,
|
.context = @ptrCast(*anyopaque, context),
|
||||||
|
|
||||||
.callErased = struct {
|
.callErased = struct {
|
||||||
fn callErased(erased: *anyopaque, input: In) Out {
|
fn callErased(erased: *anyopaque, input: In) Out {
|
||||||
return invoke(if (Captures == void) {} else @ptrCast(*Captures,
|
return invoke(@ptrCast(*Context, @alignCast(
|
||||||
@alignCast(@alignOf(Captures), erased)).*, input);
|
@alignOf(Context), erased)).*, input);
|
||||||
}
|
}
|
||||||
}.callErased,
|
}.callErased,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Captures != void)
|
|
||||||
@ptrCast(*Captures, @alignCast(captures_align, &function.context)).* = captures;
|
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue