|
| 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); |
0 commit comments