Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion rustler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ rust-version = "1.91"

[features]
big_integer = ["dep:num-bigint"]
default = ["nif_version_2_15"]
default = ["nif_version_2_15", "async-rt", "tokio-rt"]
derive = []
allocator = []
nif_version_2_14 = []
nif_version_2_15 = ["nif_version_2_14"]
nif_version_2_16 = ["nif_version_2_15"]
nif_version_2_17 = ["nif_version_2_16"]
serde = ["dep:serde"]
async-rt = []
tokio-rt = ["async-rt", "dep:tokio", "dep:futures-core"]

[dependencies]
inventory = "0.3"
rustler_codegen = { path = "../rustler_codegen", version = "0.37.1"}
num-bigint = { version = "0.4", optional = true }
serde = { version = "1", optional = true }
tokio = { version = "1", optional = true, features = ["rt", "rt-multi-thread", "sync"] }
futures-core = { version = "0.3", optional = true }
once_cell = "1"

[target.'cfg(not(windows))'.dependencies]
libloading = "0.9"
Expand Down
3 changes: 3 additions & 0 deletions rustler/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,9 @@ fn main() {
let dest_path = Path::new(&out_dir).join(SNIPPET_NAME);
fs::write(dest_path, api).unwrap();

// Tell Cargo that rustler_unstable is a valid cfg
println!("cargo::rustc-check-cfg=cfg(rustler_unstable)");

// The following lines are important to tell Cargo to recompile if something changes.
println!("cargo:rerun-if-changed=build.rs");
}
8 changes: 8 additions & 0 deletions rustler/src/codegen_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ unsafe impl NifReturnable for OwnedBinary {
}
}

// Allow returning NifReturned directly from NIFs
// This is useful for advanced use cases like yielding NIFs
unsafe impl NifReturnable for NifReturned {
unsafe fn into_returned(self, _env: Env) -> NifReturned {
self
}
}

pub enum NifReturned {
Term(NIF_TERM),
Raise(NIF_TERM),
Expand Down
38 changes: 35 additions & 3 deletions rustler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![deny(warnings)]
#![allow(non_camel_case_types)]
#![allow(clippy::missing_safety_doc)]

Expand Down Expand Up @@ -58,7 +59,7 @@ pub use crate::schedule::SchedulerFlags;
pub mod env;
pub use crate::env::{Env, OwnedEnv};
pub mod thread;
pub use crate::thread::{spawn, JobSpawner, ThreadSpawner};
pub use crate::thread::{JobSpawner, ThreadSpawner};

pub mod error;
pub use crate::error::Error;
Expand All @@ -73,8 +74,8 @@ pub use nif::Nif;
pub type NifResult<T> = Result<T, Error>;

pub use rustler_codegen::{
init, nif, resource_impl, NifException, NifMap, NifRecord, NifStruct, NifTaggedEnum, NifTuple,
NifUnitEnum, NifUntaggedEnum,
init, nif, resource_impl, task, NifException, NifMap, NifRecord, NifStruct, NifTaggedEnum,
NifTuple, NifUnitEnum, NifUntaggedEnum,
};

#[cfg(feature = "serde")]
Expand All @@ -83,4 +84,35 @@ pub mod serde;
#[cfg(feature = "serde")]
pub use crate::serde::SerdeTerm;

#[cfg(feature = "async-rt")]
pub mod runtime;

/// Spawn an async task on the global runtime.
///
/// This provides a runtime-agnostic API similar to `tokio::spawn()`.
/// The future is spawned on the global runtime and executed to completion.
///
/// Returns a join handle that can be used to await the result or cancel the task.
///
/// # Example
///
/// ```ignore
/// let handle = rustler::spawn(async {
/// // Your async code
/// process_data().await
/// });
/// ```
///
/// # Panics
///
/// Panics if the runtime fails to spawn the task.
#[cfg(feature = "tokio-rt")]
pub fn spawn<F>(future: F) -> tokio::task::JoinHandle<F::Output>
where
F: std::future::Future + Send + 'static,
F::Output: Send + 'static,
{
runtime::handle().spawn(future)
}

pub mod sys;
30 changes: 30 additions & 0 deletions rustler/src/runtime/async_runtime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::future::Future;
use std::pin::Pin;

/// Trait for pluggable async runtimes.
///
/// This allows users to provide their own async runtime implementation
/// instead of being locked into Tokio.
///
/// # Example
///
/// ```ignore
/// use rustler::runtime::AsyncRuntime;
/// use std::future::Future;
/// use std::pin::Pin;
///
/// struct MyRuntime;
///
/// impl AsyncRuntime for MyRuntime {
/// fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>) {
/// // Spawn on your custom runtime
/// }
/// }
/// ```
pub trait AsyncRuntime: Send + Sync + 'static {
/// Spawn a future onto the runtime.
///
/// The future should be executed to completion, and the runtime
/// is responsible for driving it.
fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>);
}
Loading
Loading