Skip to content

Commit 22c6042

Browse files
committed
add dynamic load test
1 parent 85f384a commit 22c6042

File tree

7 files changed

+79
-0
lines changed

7 files changed

+79
-0
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ members = [
88
"rustler_tests/native/rustler_test",
99
"rustler_tests/native/rustler_bigint_test",
1010
"rustler_tests/native/deprecated_macros",
11+
"rustler_tests/native/dynamic_load",
1112
"rustler_tests/native/rustler_compile_tests",
1213
"rustler_benchmarks/native/benchmark",
1314
]

rustler_tests/lib/dynamic_data.ex

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
defmodule DynamicData.Config do
2+
def nif_data do
3+
%{priv_path: :code.priv_dir(:rustler_test) |> IO.iodata_to_binary()}
4+
end
5+
end
6+
7+
defmodule DynamicData do
8+
use Rustler,
9+
otp_app: :rustler_test,
10+
crate: :dynamic_load,
11+
load_data_fun: {DynamicData.Config, :nif_data}
12+
13+
def get_dataset, do: :erlang.nif_error(:nif_not_loaded)
14+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "dynamic_load"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
name = "dynamic_load"
8+
path = "src/lib.rs"
9+
crate-type = ["cdylib"]
10+
11+
[dependencies]
12+
rustler_bigint = { path = "../../../rustler_bigint" }
13+
rustler = { path = "../../../rustler" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use rustler::Atom;
2+
use std::{ffi::OsStr, fs::read_to_string, os::unix::prelude::OsStrExt, path::PathBuf};
3+
4+
static mut DATASET: Option<Box<str>> = None;
5+
6+
fn initialize_dataset(mut asset_path: PathBuf) {
7+
asset_path.push("demo_dataset.txt");
8+
9+
// https://github.com/elixir-lsp/elixir-ls/issues/604
10+
eprintln!("Loading dataset from {:?}.", &asset_path);
11+
12+
let data = read_to_string(asset_path).unwrap().into_boxed_str();
13+
let data = Some(data);
14+
15+
// Safety: assumes that this function is being called once when
16+
// dynamically loading this library.
17+
// `load()` is being called exactly once and OTP will not allow any other function call
18+
// before this function returns
19+
unsafe { DATASET = data };
20+
}
21+
22+
#[rustler::nif]
23+
fn get_dataset() -> &'static str {
24+
// Safety: see `initialize_dataset()`
25+
unsafe { DATASET.as_ref() }.expect("Dataset is not initialized")
26+
}
27+
28+
fn load<'a>(env: rustler::Env<'a>, args: rustler::Term<'a>) -> bool {
29+
let key = Atom::from_str(env, "priv_path").unwrap().to_term(env);
30+
let priv_path = args.map_get(key).unwrap();
31+
let priv_path = priv_path.into_binary().unwrap().as_slice();
32+
let priv_path = OsStr::from_bytes(priv_path);
33+
let asset_path = PathBuf::from(priv_path);
34+
35+
initialize_dataset(asset_path);
36+
37+
true
38+
}
39+
40+
rustler::init!("Elixir.DynamicData", [get_dataset], load = load);

rustler_tests/priv/.gitkeep

Whitespace-only changes.

rustler_tests/priv/demo_dataset.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
some random dataset
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
defmodule RustlerTest.DynamicDataTest do
2+
use ExUnit.Case, async: true
3+
4+
test "rust has access to demo_dataset.txt via dynamic priv path" do
5+
%{priv_path: path} = DynamicData.Config.nif_data()
6+
path = Path.join(path, "demo_dataset.txt")
7+
8+
assert File.read!(path) == DynamicData.get_dataset()
9+
end
10+
end

0 commit comments

Comments
 (0)