Struct ffizz_passby::Boxed

source ·
#[non_exhaustive]
pub struct Boxed<RType: Sized> { /* private fields */ }
Expand description

Boxed is used to model values that are passed by reference and where their memory allocation is managed entirely by Rust. These are represented in the C API by a pointer, with “new” and “free” functions handling creation and destruction.

The value may be opaque to C, so that it may not access fields in the struct directly, in which case RType can be any Rust type. Otherwise, if a C structure is provided, you must use #[repr(C)] to ensure that C and Rust lay out the struct identically.

Example

Define your C and Rust types, then a type alias parameterizing Boxed:

struct System {
    // ...
}
type BoxedSystem = Boxed<System>;

Then call static methods on that type alias.

Implementations§

source§

impl<RType: Sized> Boxed<RType>

source

pub unsafe fn take_nonnull(arg: *mut RType) -> RType

Take a value from C as an argument, taking ownership of the value it points to.

Be careful that the C API documents that the passed pointer cannot be used after this function is called.

If you would like to borrow the value, but leave ownership with the calling C code, use Boxed::with_ref or its variants.

This function is most common in “free” functions, but can also be used in contexts where it is ergonomic for the called function to consume the value. For example, a database connections’s execute method might reasonably consume a query argument.

db_query_t q = db_query_new();
db_query_set_filter(q, "x = 10");
db_query_add_column(q, "y");
db_result_t res = db_execute(db, q);

Here it’s natural to assume (but should also be documented) that the db_execute function takes ownership of the query.

Safety
  • arg must not be NULL (see Boxed::take for a version allowing NULL).
  • arg must be a value returned from Box::into_raw (via Boxed::return_val or Boxed::to_out_param or a variant).
  • arg becomes invalid and must not be used after this call.
Examples found in repository?
examples/status.rs (line 167)
163
164
165
166
167
168
169
pub unsafe extern "C" fn hittr_system_free(system: *mut System) {
    // SAFETY:
    //  - system is valid and not NULL (see docstring)
    //  - caller will not use system after this call (see docstring)
    unsafe { BoxedSystem::take_nonnull(system) };
    // (System is implicitly dropped)
}
source

pub unsafe fn with_ref_nonnull<T, F: FnOnce(&RType) -> T>( arg: *const RType, f: F ) -> T

Call the contained function with a shared reference to the value.

Safety
  • arg must not be NULL (see Boxed::with_ref for a version allowing NULL).
  • No other thread may mutate the value pointed to by arg until this function returns.
  • Ownership of the value remains with the caller.
Examples found in repository?
examples/status.rs (lines 234-238)
228
229
230
231
232
233
234
235
236
237
238
239
240
pub unsafe extern "C" fn hittr_system_status(system: *const System) -> hittr_status_t {
    // SAFETY:
    // - system is not NULL and valid (see docstring)
    // - system is valid for the life of this function (documented as not threadsafe)
    // - system will not be modified during the life of this function (documented as not threadsafe)
    unsafe {
        BoxedSystem::with_ref_nonnull(system, |system| {
            // SAFETY:
            // - hittr_status_t is not allocated, so no issues
            unsafe { StatusValue::return_val(system.status) }
        })
    }
}
source

pub unsafe fn with_ref_mut_nonnull<T, F: FnOnce(&mut RType) -> T>( arg: *mut RType, f: F ) -> T

Call the contained function with an exclusive reference to the value.

Safety
  • arg must not be NULL (see Boxed::with_ref_mut for a version allowing null)
  • No other thread may access the value pointed to by arg until this function returns.
  • Ownership of the value remains with the caller.
Examples found in repository?
examples/status.rs (lines 189-191)
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
pub unsafe extern "C" fn hittr_system_run(system: *mut System) {
    // SAFETY:
    // - system is not NULL and valid (see docstring)
    // - system is valid for the life of this function (documented as not threadsafe)
    // - system will not be accessed during the life of this function (documented as not threadsafe)
    unsafe {
        BoxedSystem::with_ref_mut_nonnull(system, |system| {
            system.run();
        });
    }
}

/// Record a hit on thi Hittr system.
///
/// If the sytem is not running, it will enter the failed state.  If it counts 5
/// or more hits, it will enter the failed.state.
///
/// # Safety
///
/// The system must be non-NULL and point to a valid hittr_system_t.
///
/// ```c
/// void hittr_system_count_hit(hittr_system_t *system);
/// ```
#[no_mangle]
pub unsafe extern "C" fn hittr_system_count_hit(system: *mut System) {
    // SAFETY:
    // - system is not NULL and valid (see docstring)
    // - system is valid for the life of this function (documented as not threadsafe)
    // - system will not be accessed during the life of this function (documented as not threadsafe)
    unsafe {
        BoxedSystem::with_ref_mut_nonnull(system, |system| {
            system.count_hit();
        });
    }
}
source

pub unsafe fn return_val(rval: RType) -> *mut RType

Return a value to C, boxing the value and transferring ownership.

This method is most often used in constructors, to return the built value.

Safety
  • The caller must ensure that the value is eventually freed.
Examples found in repository?
examples/status.rs (line 127)
124
125
126
127
128
pub unsafe extern "C" fn hittr_system_new() -> *mut System {
    let sys = System::new();
    // SAFETY: function docs indicate value must be freed
    unsafe { BoxedSystem::return_val(sys) }
}
source

pub unsafe fn return_val_boxed(rval: Box<RType>) -> *mut RType

Return a boxed value to C, transferring ownership.

This is an alternative to Boxed::return_val for use when the value is already boxed.

Safety
  • The caller must ensure that the value is eventually freed.
source

pub unsafe fn to_out_param(rval: RType, arg_out: *mut *mut RType)

Return a value to C, transferring ownership, via an “output parameter”.

If the pointer is NULL, the value is dropped. Use Boxed::to_out_param_nonnull to panic in this situation.

Safety
  • The caller must ensure that the value is eventually freed.
  • If not NULL, arg_out must point to valid, properly aligned memory for a pointer value.
Examples found in repository?
examples/status.rs (line 145)
142
143
144
145
146
147
148
149
150
pub unsafe extern "C" fn hittr_system_new_network(system_out: *mut *mut System, port: u16) -> bool {
    if let Ok(sys) = System::new_network(port) {
        // SAFETY: see docstring
        unsafe { BoxedSystem::to_out_param(sys, system_out) }
        true
    } else {
        false
    }
}
source

pub unsafe fn to_out_param_nonnull(rval: RType, arg_out: *mut *mut RType)

Return a value to C, transferring ownership, via an “output parameter”.

If the pointer is NULL, this function will panic. Use Boxed::to_out_param to drop the value in this situation.

Safety
  • The caller must ensure that the value is eventually freed.
  • arg_out must not be NULL.
  • arg_out must point to valid, properly aligned memory for a pointer value.
source§

impl<RType: Sized + Default> Boxed<RType>

source

pub unsafe fn take(arg: *mut RType) -> RType

Take a value from C as an argument.

This function is similar to Boxed::take_nonnull, but returns the default value of RType when given NULL.

Safety
source

pub unsafe fn with_ref<T, F: FnOnce(&RType) -> T>(arg: *const RType, f: F) -> T

Call the contained function with a shared reference to the value.

If the given pointer is NULL, the contained function is called with a reference to RType’s default value, which is subsequently dropped.

Safety
  • No other thread may mutate the value pointed to by arg until this function returns.
  • Ownership of the value remains with the caller.
source

pub unsafe fn with_ref_mut<T, F: FnOnce(&mut RType) -> T>( arg: *mut RType, f: F ) -> T

Call the contained function with an exclusive reference to the value.

If the given pointer is NULL, the contained function is called with a reference to RType’s default value, which is subsequently dropped.

Safety
  • No other thread may access the value pointed to by arg until this function returns.
  • Ownership of the value remains with the caller.

Auto Trait Implementations§

§

impl<RType> RefUnwindSafe for Boxed<RType>where RType: RefUnwindSafe,

§

impl<RType> Send for Boxed<RType>where RType: Send,

§

impl<RType> Sync for Boxed<RType>where RType: Sync,

§

impl<RType> Unpin for Boxed<RType>where RType: Unpin,

§

impl<RType> UnwindSafe for Boxed<RType>where RType: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.