zigler v0.1.1 beam View Source

This struct contains adapters designed to facilitate interfacing the BEAM's c-style helpers for NIFs with a more idiomatic Zig-style of programming, for example, the use of slices instead of null-terminated arrays as strings.

This struct derives from zig/beam/beam.zig, and you may import it into your module's zig code by calling:

const beam = @import("beam.zig")

This is done automatically for you inside your ~Z forms, so do NOT use this import statement with inline Zig.

Features

The BEAM Allocator

Wraps e.enif_alloc and e.enif_free functions into a compliant Zig allocator struct. You should thus be able to supply Zig standard library functions which require an allocator a struct that is compliant with its requirements.

This is, in particular, useful for slice generation.

Example (slice generation)

beam = @import("beam.zig");

fn make_a_slice_of_floats() ![]f32 {
  return beam.allocator.alloc(f32, 100);
}

Beacuse Zig features composable allocators, you can very easily implement custom allocators on top of the existing BEAM allocator.

Getters

Erlang's NIF interface provides a comprehensive set of methods to retrieve data out of BEAM terms. However, this set of methods presents an error handling scheme that is designed for C and inconsistent with the idiomatic scheme used for Zig best practices.

A series of get functions is provided, implementing these methods in accordance to best practices. These include get/3, which is the generic method for getting scalar values, get_X, which are typed methods for retrieving scalar values, and get_slice_of/3, which is the generic method for retrieving a Zig slice from a BEAM list.

Naturally, for all of these functions, you will have to provide the BEAM environment value.

Examples

const beam = @import("beam.zig");

fn double_value(env: beam.env, value: beam.term) !f64 {
  return (try beam.get_f64(env, value)) * 2;
}

fn sum_float_list(env: beam.env, list: beam.term) !f64 {
  zig_list: []f64 = try beam.get_slice_of(f64, env, list);
  defer beam.allocator.free(zig_list);  // don't forget to clean up!

  result: f64 = 0;
  for (list) |item| { result += item; }
  return result;
}

Makers

A series of "make" functions is provided which allow for easy export of Zig values back to the BEAM. Typically, these functions are used in the automatic type marshalling performed by Zigler, however, you may want to be able to use them yourself to assemble BEAM datatypes not directly supported by Zig. For example, a custom tuple value.

Example

const beam = @import("beam.zig");

const ok_slice="ok"[0..];
fn to_ok_tuple(env: beam.env, value: i64) !beam.term {
  tuple_slice: []term = try beam.allocator.alloc(beam.term, 2);

  tuple_slice[0] = beam.make_atom(env, ok_slice);
  tuple_slice[1] = beam.make_i64(env, value);

  return beam.make_tuple(tuple_slice);
}

Link to this section Summary

Functions

A helper for marshalling values from the BEAM runtime into Zig. Use this function if you need support for Zig generics.

Takes a BEAM int term and returns a c_int value. Should only be used for C interop with Zig functions.

Takes a BEAM int term and returns a c_long value. Should only be used for C interop with Zig functions.

Takes a BEAM int term and returns a isize value. Should only be used for C interop.

Takes a BEAM int term and returns a usize value. Zig idiomatically uses usize for its size values, so typically you should be using this function.

Takes a BEAM int term and returns a u8 value.

Takes a BEAM int term and returns an i32 value.

Takes a BEAM int term and returns an i64 value.

Takes a BEAM float term and returns an f16 value.

Takes a BEAM float term and returns an f32 value.

Takes a BEAM float term and returns an f64 value.

Takes a BEAM atom term and retrieves it as a slice []u8 value. it's the caller's responsibility to make sure that the value is freed.

Takes a BEAM atom term and retrieves it as a slice []u8 value, with any allocator.

Takes an BEAM Kernel.binary/0 term and retrieves a pointer to the binary data as a Zig c-string ([*c]u8). No memory is allocated for this operation.

Takes an BEAM Kernel.binary/0 term and retrieves it as a Zig character slice ([]u8) No memory is allocated for this operation.

Takes an BEAM Kernel.binary/0 term and returns the corresponding binary struct.

Takes an BEAM Kernel.pid/0 term and returns the corresponding pid struct.

Takes an Beam tuple/0 term and returns it as a slice of term structs. Does not allocate memory for this operation.

Takes a BEAM list/0 term and returns its length.

A generic function which lets you convert a BEAM list/0 of homogeous type into a Zig slice.

Converts an BEAM list/0 of homogenous type into a Zig slice, but using any allocator you wish.

Converts an BEAM boolean/0 into a Zig bool.

A helper for marshalling values from Zig back into the runtime. Use this function if you need support for Zig generics.

converts a char (u8) value into a BEAM integer/0.

converts a c_int value into a BEAM integer/0.

converts a c_long value into a BEAM integer/0.

converts an isize value into a BEAM integer/0.

converts a usize value into a BEAM integer/0.

converts an i32 value into a BEAM integer/0.

converts an i64 value into a BEAM integer/0.

converts an f16 value into a BEAM float/0.

converts an f32 value into a BEAM float/0.

converts an f64 value into a BEAM float/0.

converts a Zig char slice ([]u8) into a BEAM atom/0.

converts a Zig char slice ([]u8) into a BEAM binary/0.

converts an c string ([*c]u8) into a BEAM binary/0. Mostly used for c interop.

converts a slice of terms into a BEAM tuple/0.

converts a slice of terms into a BEAM list/0.

converts a Zig char slice ([]u8) into a BEAM charlist/0.

A helper to make BEAM lists out of slices of term. Use this function if you need a generic listbuilding function.

A helper to make a BEAM t:Kernel.list out of terms, with any allocator. Use this function if you need a generic listbuilding function.

converts a c_int slice ([]c_int) into a BEAM list of integer/0.

converts a c_long slice ([]c_long) into a BEAM list of integer/0.

converts an i32 slice ([]i32) into a BEAM list of integer/0.

converts an i64 slice ([]i64) into a BEAM list of integer/0.

converts an f16 slice ([]f16) into a BEAM list of float/0.

converts an f32 slice ([]f32) into a BEAM list of float/0.

converts an f64 slice ([]f64) into a BEAM list of float/0.

This function is used to communicate :enomem back to the BEAM as an exception.

This function is used to communicate :function_clause back to the BEAM as an exception.

This function is used to communicate :assertion_error back to the BEAM as an exception.

A function used to return assertion errors to a zigtest.

Link to this section Functions

Link to this function

get(comptime T: type, environment: env, value: term) !T

View Source (comptime)

A helper for marshalling values from the BEAM runtime into Zig. Use this function if you need support for Zig generics.

Used internally to typcheck values coming into Zig slice.

supported types:

  • c_int
  • c_long
  • isize
  • usize
  • u8
  • i32
  • i64
  • f16
  • f32
  • f64
Link to this function

get_c_int(environment: env, src_term: term) !c_int

View Source

Takes a BEAM int term and returns a c_int value. Should only be used for C interop with Zig functions.

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_c_long(environment: env, src_term: term) !c_long

View Source

Takes a BEAM int term and returns a c_long value. Should only be used for C interop with Zig functions.

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_isize(environment: env, src_term: term) !isize

View Source

Takes a BEAM int term and returns a isize value. Should only be used for C interop.

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_usize(environment: env, src_term: term) !usize

View Source

Takes a BEAM int term and returns a usize value. Zig idiomatically uses usize for its size values, so typically you should be using this function.

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_u8(environment: env, src_term: term) !u8

View Source

Takes a BEAM int term and returns a u8 value.

Note that this conversion function checks to make sure it's in range (0..255).

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_i32(environment: env, src_term: term) !i32

View Source

Takes a BEAM int term and returns an i32 value.

Note that this conversion function does not currently do range checking.

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_i64(environment: env, src_term: term) !i64

View Source

Takes a BEAM int term and returns an i64 value.

Note that this conversion function does not currently do range checking.

Raises beam.Error.FunctionClauseError if the term is not integer/0

Link to this function

get_f16(environment: env, src_term: term) !f16

View Source

Takes a BEAM float term and returns an f16 value.

Note that this conversion function does not currently do range checking.

Raises beam.Error.FunctionClauseError if the term is not float/0

Link to this function

get_f32(environment: env, src_term: term) !f32

View Source

Takes a BEAM float term and returns an f32 value.

Note that this conversion function does not currently do range checking.

Raises beam.Error.FunctionClauseError if the term is not float/0

Link to this function

get_f64(environment: env, src_term: term) !f64

View Source

Takes a BEAM float term and returns an f64 value.

Raises beam.Error.FunctionClauseError if the term is not float/0

Link to this function

get_atom_slice(environment: env, src_term: atom) ![]u8

View Source

Takes a BEAM atom term and retrieves it as a slice []u8 value. it's the caller's responsibility to make sure that the value is freed.

Uses the standard beam.allocator allocator. If you require a custom allocator, use get_atom_slice_alloc/3

Raises beam.Error.FunctionClauseError if the term is not atom/0

Link to this function

get_atom_slice_alloc(a: *Allocator, environment: env, src_term: atom) ![]u8

View Source

Takes a BEAM atom term and retrieves it as a slice []u8 value, with any allocator.

Raises beam.Error.FunctionClauseError if the term is not atom/0

Link to this function

get_c_string(environment: env, src_term: term) ![*c]u8

View Source

Takes an BEAM Kernel.binary/0 term and retrieves a pointer to the binary data as a Zig c-string ([*c]u8). No memory is allocated for this operation.

Should only be used for c interop functions.

Note: this function could have unexpected results if your BEAM binary contains any zero byte values. Always use get_char_slice/2 when C-interop is not necessary.

Raises beam.Error.FunctionClauseError if the term is not Kernel.binary/0

Link to this function

get_char_slice(environment: env, src_term: term) ![]u8

View Source

Takes an BEAM Kernel.binary/0 term and retrieves it as a Zig character slice ([]u8) No memory is allocated for this operation.

Raises beam.Error.FunctionClauseError if the term is not Kernel.binary/0

Link to this function

get_binary(environment: env, src_term: term) !binary

View Source

Takes an BEAM Kernel.binary/0 term and returns the corresponding binary struct.

Raises beam.Error.FunctionClauseError if the term is not Kernel.binary/0

Link to this function

get_pid(environment: env, src_term: term) !pid

View Source

Takes an BEAM Kernel.pid/0 term and returns the corresponding pid struct.

Note that this is a fairly opaque struct and you're on your own as to what you can do with this (for now), except as a parameter for the e.ErlNifSend function.

Raises beam.Error.FunctionClauseError if the term is not Kernel.pid/0

Link to this function

get_tuple(environment: env, src_term: term) ![]term

View Source

Takes an Beam tuple/0 term and returns it as a slice of term structs. Does not allocate memory for this operation.

Raises beam.Error.FunctionClauseError if the term is not tuple/0

Link to this function

get_list_length(environment: env, list: term) !usize

View Source

Takes a BEAM list/0 term and returns its length.

Raises beam.Error.FunctionClauseError if the term is not list/0

Link to this function

get_head_and_iter(environment: env, list: *term) !term

View Source

Iterates over a BEAM list/0.

In this function, the list value will be modified to the tl of the BEAM list, and the return value will be the BEAM term.

Raises beam.Error.FunctionClauseError if the term is not list/0

Link to this function

get_slice_of(comptime T: type, environment: env, list: term) ![]T

View Source (comptime)

A generic function which lets you convert a BEAM list/0 of homogeous type into a Zig slice.

The resulting slice will be allocated using the beam allocator, with ownership passed to the caller. If you need to use a different allocator, use get_slice_of_alloc/4

Raises beam.Error.FunctionClauseError if the term is not list/0. Also raises beam.Error.FunctionClauseError if any of the terms is incompatible with the internal type

supported internal types:

  • c_int
  • c_long
  • isize
  • usize
  • u8
  • i32
  • i64
  • f16
  • f32
  • f64
Link to this function

get_slice_of_alloc(comptime T: type, a: *Allocator, environment: env, list: term) ![]T

View Source (comptime)

Converts an BEAM list/0 of homogenous type into a Zig slice, but using any allocator you wish.

ownership is passed to the caller.

Raises beam.Error.FunctionClauseError if the term is not list/0. Also raises beam.Error.FunctionClauseError if any of the terms is incompatible with the internal type.

supported internal types:

  • c_int
  • c_long
  • isize
  • usize
  • u8
  • i32
  • i64
  • f16
  • f32
  • f64
Link to this function

get_bool(environment: env, val: term) !bool

View Source

Converts an BEAM boolean/0 into a Zig bool.

Raises beam.Error.FunctionClauseError if the term is not boolean/0. May potentially raise an out of memory error, as it must make an allocation to perform its conversion.

Link to this function

make(comptime T: type, environment: env, val: T) term

View Source (comptime)

A helper for marshalling values from Zig back into the runtime. Use this function if you need support for Zig generics.

supported types:

  • c_int
  • c_long
  • isize
  • usize
  • u8
  • i32
  • i64
  • f16
  • f32
  • f64
Link to this function

make_u8(environment: env, chr: u8) term

View Source

converts a char (u8) value into a BEAM integer/0.

Link to this function

make_c_int(environment: env, val: c_int) term

View Source

converts a c_int value into a BEAM integer/0.

Link to this function

make_c_long(environment: env, val: c_long) term

View Source

converts a c_long value into a BEAM integer/0.

Link to this function

make_isize(environment: env, val: isize) term

View Source

converts an isize value into a BEAM integer/0.

Link to this function

make_usize(environment: env, val: usize) term

View Source

converts a usize value into a BEAM integer/0.

Link to this function

make_i32(environment: env, val: i32) term

View Source

converts an i32 value into a BEAM integer/0.

Link to this function

make_i64(environment: env, val: i64) term

View Source

converts an i64 value into a BEAM integer/0.

Link to this function

make_f16(environment: env, val: f16) term

View Source

converts an f16 value into a BEAM float/0.

Link to this function

make_f32(environment: env, val: f32) term

View Source

converts an f32 value into a BEAM float/0.

Link to this function

make_f64(environment: env, val: f64) term

View Source

converts an f64 value into a BEAM float/0.

Link to this function

make_atom(environment: env, atom_str: []const u8) term

View Source

converts a Zig char slice ([]u8) into a BEAM atom/0.

Link to this function

make_slice(environment: env, val: []u8) term

View Source

converts a Zig char slice ([]u8) into a BEAM binary/0.

no memory allocation inside of Zig is performed and the BEAM environment is responsible for the resulting binary. You are responsible for managing the allocation of the slice.

Link to this function

make_c_string(environment: env, val: [*c]u8) term

View Source

converts an c string ([*c]u8) into a BEAM binary/0. Mostly used for c interop.

no memory allocation inside of Zig is performed and the BEAM environment is responsible for the resulting binary. You are responsible for managing the allocation of the slice.

Link to this function

make_tuple(environment: env, val: []term) term

View Source

converts a slice of terms into a BEAM tuple/0.

Link to this function

make_term_list(environment: env, val: []term) term

View Source

converts a slice of terms into a BEAM list/0.

Link to this function

make_charlist(environment: env, val: []u8) term

View Source

converts a Zig char slice ([]u8) into a BEAM charlist/0.

Link to this function

make_cstring_charlist(environment: env, val: [*c]u8) term

View Source

converts a c string ([*c]u8) into a BEAM charlist/0.

Link to this function

make_list(comptime T: type, environment: env, val: []T) !term

View Source (comptime)

A helper to make BEAM lists out of slices of term. Use this function if you need a generic listbuilding function.

uses the BEAM allocator internally. If you would like to use a custom allocator, (for example an arena allocator, if you have very long lists), use make_list_alloc/4

supported internal types:

  • c_int
  • c_long
  • isize
  • usize
  • u8
  • i32
  • i64
  • f16
  • f32
  • f64
Link to this function

make_list_alloc(comptime T: type, a: *Allocator, environment: env, val: []T) !term

View Source (comptime)

A helper to make a BEAM t:Kernel.list out of terms, with any allocator. Use this function if you need a generic listbuilding function.

supported internal types:

  • c_int
  • c_long
  • isize
  • usize
  • u8
  • i32
  • i64
  • f16
  • f32
  • f64
Link to this function

make_c_int_list(environment: env, val: []c_int) !term

View Source

converts a c_int slice ([]c_int) into a BEAM list of integer/0.

Link to this function

make_c_long_list(environment: env, val: []c_long) !term

View Source

converts a c_long slice ([]c_long) into a BEAM list of integer/0.

Link to this function

make_i32_list(environment: env, val: []i32) !term

View Source

converts an i32 slice ([]i32) into a BEAM list of integer/0.

Link to this function

make_i64_list(environment: env, val: []i64) !term

View Source

converts an i64 slice ([]i64) into a BEAM list of integer/0.

Link to this function

make_f16_list(environment: env, val: []f16) !term

View Source

converts an f16 slice ([]f16) into a BEAM list of float/0.

Link to this function

make_f32_list(environment: env, val: []f32) !term

View Source

converts an f32 slice ([]f32) into a BEAM list of float/0.

Link to this function

make_f64_list(environment: env, val: []f64) !term

View Source

converts an f64 slice ([]f64) into a BEAM list of float/0.

Link to this function

make_bool(environment: env, val: bool) term

View Source

converts a bool value into a Kernel.boolean/0 value.

Link to this function

throw_enomem(environment: env) term

View Source

This function is used to communicate :enomem back to the BEAM as an exception.

The BEAM is potentially OOM-safe, and Zig lets you leverage that. OOM errors from beam.allocator can be converted to a generic erlang term that represents an exception. Returning this from your NIF results in a BEAM throw event.

Link to this function

throw_function_clause_error(environment: env) term

View Source

This function is used to communicate :function_clause back to the BEAM as an exception.

By default Zigler will do parameter input checking on value ingress from the dynamic BEAM runtime to the static Zig runtime. You can also use this function to communicate a similar error by returning the resulting term from your NIF.

Link to this function

throw_assertion_error(environment: env) term

View Source

This function is used to communicate :assertion_error back to the BEAM as an exception.

Used when running Zigtests, when trapping beam.AssertionError.AssertionError.

A function used to return assertion errors to a zigtest.

Zig's std.assert() will panic the Zig runtime and therefore the entire BEAM VM, making it incompatible with Elixir's Unit tests. As the VM is required for certain functionality (like e.enif_alloc), a BEAM-compatible assert is necessary.

When building zigtests, assert(...) calls get lexically converted to try beam.assert(...) calls.