From 5208d74f28e0bac69994a3be2c5036fc519b29cf Mon Sep 17 00:00:00 2001 From: kaaboyae Date: Thu, 30 Dec 2021 00:03:42 +0100 Subject: [PATCH] add load_data_fun config option --- rustler_mix/lib/rustler.ex | 51 +++++++++++++++++++++- rustler_mix/lib/rustler/compiler/config.ex | 1 + 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/rustler_mix/lib/rustler.ex b/rustler_mix/lib/rustler.ex index 3aa4ba7cb..7bb41e5ce 100644 --- a/rustler_mix/lib/rustler.ex +++ b/rustler_mix/lib/rustler.ex @@ -43,6 +43,24 @@ defmodule Rustler do * `:load_data` - Any valid term. This value is passed into the NIF when it is loaded (default: `0`) + * `:load_data_fun` - `{Module, :function}` to dynamically generate `load_data`. + Default value: `nil`. + + This parameter is mutually exclusive with `load_data` + which means that `load_data` has to be set to it's default value. + + Example + + defmodule NIF do + use Rustler, load_data: {Deployment, :nif_data} + end + + defmodule Deployment do + def nif_data do + :code.priv_dir(:otp_app) |> IO.iodata_to_binary() + end + end + * `:load_from` - This option allows control over where the final artifact should be loaded from at runtime. By default the compiled artifact is loaded from the owning `:otp_app`'s `priv/native` directory. This option comes in handy in @@ -89,6 +107,7 @@ defmodule Rustler do if config.lib do @load_from config.load_from @load_data config.load_data + @load_data_fun config.load_data_fun @before_compile Rustler end @@ -112,11 +131,41 @@ defmodule Rustler do |> Application.app_dir(path) |> to_charlist() - :erlang.load_nif(load_path, @load_data) + load_data = Rustler.construct_load_data(@load_data, @load_data_fun) + + :erlang.load_nif(load_path, load_data) end end end + @doc false + def construct_load_data(load_data, load_data_fun) do + default_load_data_value = %Rustler.Compiler.Config{}.load_data + default_fun_value = %Rustler.Compiler.Config{}.load_data_fun + + case {load_data, load_data_fun} do + {load_data, ^default_fun_value} -> + load_data + + {^default_load_data_value, {module, function}} + when is_atom(module) and is_atom(function) -> + apply(module, function, []) + + {^default_load_data_value, provided_value} -> + raise """ + `load_data` has to be `{Module, :function}`. + Instead received: #{inspect(provided_value)} + """ + + {load_data, load_data_fun} -> + raise """ + Only `load_data` or `load_data_fun` can be provided. Instead received: + >>> load_data: #{inspect(load_data)} + >>> load_data_fun: #{inspect(load_data_fun)} + """ + end + end + @doc false def rustler_version, do: "0.23.0" diff --git a/rustler_mix/lib/rustler/compiler/config.ex b/rustler_mix/lib/rustler/compiler/config.ex index c14656952..31a163238 100644 --- a/rustler_mix/lib/rustler/compiler/config.ex +++ b/rustler_mix/lib/rustler/compiler/config.ex @@ -19,6 +19,7 @@ defmodule Rustler.Compiler.Config do features: [], lib: true, load_data: 0, + load_data_fun: nil, load_from: nil, mode: :release, otp_app: nil,