Skip to content

Instantly share code, notes, and snippets.

@jackalcooper
Created July 27, 2022 01:11
Show Gist options
  • Save jackalcooper/76249a52eb576afa15928c7ede5fa415 to your computer and use it in GitHub Desktop.
Save jackalcooper/76249a52eb576afa15928c7ede5fa415 to your computer and use it in GitHub Desktop.
Zig managed NIF resource
pub fn ResourceKind(comptime ElementType: type, module_name: anytype) type {
return struct {
pub const T = ElementType;
pub const module_name = module_name;
pub const resource = struct {
pub var t: resource_type = undefined;
pub const name = @typeName(ElementType);
pub fn make(environment: env, value: T) !term {
return make_resource(environment, value, t);
}
pub fn fetch(environment: env, arg: term) !T {
return fetch_resource(T, environment, t, arg);
}
pub fn fetch_ptr(environment: env, arg: term) !*T {
return fetch_resource_ptr(T, environment, t, arg);
}
};
const PtrType = [*c]ElementType;
pub const Ptr = struct {
pub const T = PtrType;
pub const resource = struct {
pub var t: resource_type = undefined;
pub const name = @typeName(PtrType);
pub fn make(environment: env, value: PtrType) !term {
return make_resource(environment, value, t);
}
pub fn fetch(environment: env, arg: term) !PtrType {
return fetch_resource(PtrType, environment, t, arg);
}
};
};
const ArrayType = [*c]const ElementType;
pub const Array = struct {
pub const T = ArrayType;
pub const resource = struct {
pub var t: resource_type = undefined;
pub const name = @typeName(ArrayType);
pub fn make(environment: env, value: ArrayType) !term {
return make_resource(environment, value, t);
}
pub fn fetch(environment: env, arg: term) !ArrayType {
return fetch_resource(ArrayType, environment, t, arg);
}
};
};
fn ptr(environment: env, _: c_int, args: [*c]const term) callconv(.C) term {
return get_resource_ptr_from_term(T, environment, @This().resource.t, Ptr.resource.t, args[0]) catch return make_error_binary(environment, "fail to create ptr " ++ @typeName(T));
}
pub fn opaque_ptr(environment: env, _: c_int, args: [*c]const term) callconv(.C) term {
const ptr_to_resource_memory: Ptr.T = fetch_resource_ptr(T, environment, @This().resource.t, args[0]) catch return make_error_binary(environment, "fail to create ptr " ++ @typeName(T));
return InternalOpaquePtr.resource.make(environment, ptr_to_resource_memory) catch return make_error_binary(environment, "fail to make resource for: " ++ @typeName(InternalOpaquePtr.T));
}
fn array(environment: env, _: c_int, args: [*c]const term) callconv(.C) term {
return get_resource_array_from_list(T, environment, @This().resource.t, Array.resource.t, args[0]) catch return make_error_binary(environment, "fail to create array " ++ @typeName(T));
}
fn mut_array(environment: env, _: c_int, args: [*c]const term) callconv(.C) term {
return get_resource_array_from_list(T, environment, @This().resource.t, Ptr.resource.t, args[0]) catch return make_error_binary(environment, "fail to create mut array " ++ @typeName(T));
}
fn primitive(environment: env, _: c_int, args: [*c]const term) callconv(.C) term {
const v = resource.fetch(environment, args[0]) catch return make_error_binary(environment, "fail to extract pritimive from " ++ @typeName(T));
return make(T, environment, v) catch return make_error_binary(environment, "fail to create primitive " ++ @typeName(T));
}
fn make_(environment: env, _: c_int, args: [*c]const term) callconv(.C) term {
const v = get(T, environment, args[0]) catch return make_error_binary(environment, "fail to fetch " ++ @typeName(T));
return resource.make(environment, v) catch return make_error_binary(environment, "fail to create " ++ @typeName(T));
}
pub const nifs = .{
e.ErlNifFunc{ .name = module_name ++ ".ptr", .arity = 1, .fptr = ptr, .flags = 0 },
e.ErlNifFunc{ .name = module_name ++ ".opaque_ptr", .arity = 1, .fptr = opaque_ptr, .flags = 0 },
e.ErlNifFunc{ .name = module_name ++ ".array", .arity = 1, .fptr = array, .flags = 0 },
e.ErlNifFunc{ .name = module_name ++ ".mut_array", .arity = 1, .fptr = mut_array, .flags = 0 },
e.ErlNifFunc{ .name = module_name ++ ".primitive", .arity = 1, .fptr = primitive, .flags = 0 },
e.ErlNifFunc{ .name = module_name ++ ".make", .arity = 1, .fptr = make_, .flags = 0 },
};
pub fn open(environment: env) void {
@This().resource.t = e.enif_open_resource_type(environment, null, @This().resource.name, destroy_do_nothing, e.ERL_NIF_RT_CREATE | e.ERL_NIF_RT_TAKEOVER, null);
}
pub fn open_ptr(environment: env) void {
@This().Ptr.resource.t = e.enif_open_resource_type(environment, null, @This().Ptr.resource.name, destroy_do_nothing, e.ERL_NIF_RT_CREATE | e.ERL_NIF_RT_TAKEOVER, null);
}
pub fn open_array(environment: env) void {
@This().Array.resource.t = e.enif_open_resource_type(environment, null, @This().Array.resource.name, destroy_do_nothing, e.ERL_NIF_RT_CREATE | e.ERL_NIF_RT_TAKEOVER, null);
}
pub fn open_all(environment: env) void {
open(environment);
open_ptr(environment);
open_array(environment);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment