diplomat_runtime/lib.rs
1#![cfg_attr(not(any(target_arch = "wasm32")), no_std)]
2
3//! The [Diplomat](https://rust-diplomat.github.io/diplomat/) runtime crate.
4//!
5//! This crate provides Diplomat-specific types for crates writing `#[diplomat::bridge]` modules.
6//! Include this in any crate that also depends on `diplomat`, since `#[diplomat::bridge]`
7//! will generate code that relies on types from here.
8//!
9//! This crate contains a fair number of `DiplomatFoo` types. Some, like
10//! [`DiplomatOption`], are FFI-safe versions of Rust types that can be put in
11//! a struct and passed safely over FFI. Others, like [`DiplomatChar`], are simple
12//! type aliases that signal to the Diplomat tool that particular semantics are desired
13//! on the C++ side.
14//!
15//! # Features
16//!
17//! The `log` feature enables logging support, currently enabled via the wasm-only `diplomat_init()`.
18//!
19//! The `jvm-callback-support` feature should be enabled if building Diplomat for use in the JVM, for
20//! a Diplomat-based library that uses callbacks.
21extern crate alloc;
22
23use alloc::alloc::Layout;
24
25#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
26mod wasm_glue;
27
28mod write;
29pub use write::DiplomatWrite;
30pub use write::{diplomat_buffer_write_create, diplomat_buffer_write_destroy};
31mod slices;
32pub use slices::{
33 DiplomatOwnedSlice, DiplomatOwnedStr16Slice, DiplomatOwnedStrSlice, DiplomatOwnedUTF8StrSlice,
34 DiplomatSlice, DiplomatSliceMut, DiplomatStr16Slice, DiplomatStrSlice, DiplomatUtf8StrSlice,
35};
36
37mod callback;
38pub use callback::DiplomatCallback;
39
40mod result;
41pub use result::{DiplomatOption, DiplomatResult};
42
43pub mod rust_interop;
44
45/// Like [`char`], but unvalidated.
46///
47/// This type will usually map to some character type in the target language, and
48/// you will not need to worry about the safety of mismatched string invariants.
49pub type DiplomatChar = u32;
50
51/// Like [`str`], but unvalidated.
52///
53/// This is a dynamically sized type, it should be used behind an `&` or a `Box<T>`
54///
55/// This type will usually map to some string type in the target language, and
56/// you will not need to worry about the safety of mismatched string invariants.
57pub type DiplomatStr = [u8];
58
59/// Like `Wstr`, but unvalidated.
60///
61/// This is a dynamically sized type, it should be used behind an `&` or a `Box<T>`
62///
63/// This type will usually map to some string type in the target language, and
64/// you will not need to worry about the safety of mismatched string invariants.
65pub type DiplomatStr16 = [u16];
66
67/// Like [`u8`], but interpreted explicitly as a raw byte as opposed to a numerical value.
68///
69/// This matters for languages like JavaScript or Dart, where there's only a single numeric
70/// type, but special types for byte buffers.
71pub type DiplomatByte = u8;
72
73/// Allocates a buffer of a given size in Rust's memory.
74///
75/// Primarily to be called by generated FFI bindings, not Rust code, but is available if needed.
76///
77/// # Safety
78/// - The allocated buffer must be freed with [`diplomat_free()`].
79#[no_mangle]
80pub unsafe extern "C" fn diplomat_alloc(size: usize, align: usize) -> *mut u8 {
81 alloc::alloc::alloc(Layout::from_size_align(size, align).unwrap())
82}
83
84/// Frees a buffer that was allocated in Rust's memory.
85///
86/// Primarily to be called by generated FFI bindings, not Rust code, but is available if needed.
87///
88/// # Safety
89/// - `ptr` must be a pointer to a valid buffer allocated by [`diplomat_alloc()`].
90#[no_mangle]
91pub unsafe extern "C" fn diplomat_free(ptr: *mut u8, size: usize, align: usize) {
92 alloc::alloc::dealloc(ptr, Layout::from_size_align(size, align).unwrap())
93}
94
95/// Whether a `&[u8]` is a `&str`.
96///
97/// Primarily to be called by generated FFI bindings, not Rust code, but is available if needed.
98///
99/// # Safety
100/// - `ptr` and `size` must be a valid `&[u8]`
101#[no_mangle]
102pub unsafe extern "C" fn diplomat_is_str(ptr: *const u8, size: usize) -> bool {
103 core::str::from_utf8(core::slice::from_raw_parts(ptr, size)).is_ok()
104}