always implement traits for C type

This commit is contained in:
Dustin J. Mitchell
2022-02-06 23:05:33 +00:00
parent 1e585ba0d9
commit e11506ee6a
8 changed files with 60 additions and 59 deletions

View File

@@ -2,29 +2,30 @@
/// values are implicitly copyable, via C's struct assignment.
///
/// The Rust and C types may differ, with from_ctype and as_ctype converting between them.
/// Implement this trait for the C type.
pub(crate) trait PassByValue: Sized {
type CType;
type RustType;
/// Convert a C value to a Rust value.
///
/// # Safety
///
/// `arg` must be a valid CType.
unsafe fn from_ctype(arg: Self::CType) -> Self;
/// `self` must be a valid CType.
unsafe fn from_ctype(self) -> Self::RustType;
/// Convert a Rust value to a C value.
fn as_ctype(self) -> Self::CType;
fn as_ctype(arg: Self::RustType) -> Self;
/// Take a value from C as an argument.
///
/// # Safety
///
/// `arg` must be a valid CType. This is typically ensured either by requiring that C
/// `self` must be a valid CType. This is typically ensured either by requiring that C
/// code not modify it, or by defining the valid values in C comments.
unsafe fn from_arg(arg: Self::CType) -> Self {
unsafe fn from_arg(arg: Self) -> Self::RustType {
// SAFETY:
// - arg is a valid CType (promised by caller)
unsafe { Self::from_ctype(arg) }
unsafe { arg.from_ctype() }
}
/// Take a value from C as a pointer argument, replacing it with the given value. This is used
@@ -33,7 +34,7 @@ pub(crate) trait PassByValue: Sized {
/// # Safety
///
/// `*arg` must be a valid CType, as with [`from_arg`].
unsafe fn take_from_arg(arg: *mut Self::CType, mut replacement: Self::CType) -> Self {
unsafe fn take_from_arg(arg: *mut Self, mut replacement: Self) -> Self::RustType {
// SAFETY:
// - arg is valid (promised by caller)
// - replacement is valid (guaranteed by Rust)
@@ -44,8 +45,8 @@ pub(crate) trait PassByValue: Sized {
}
/// Return a value to C
fn return_val(self) -> Self::CType {
self.as_ctype()
fn return_val(arg: Self::RustType) -> Self {
Self::as_ctype(arg)
}
/// Return a value to C, via an "output parameter"
@@ -54,12 +55,12 @@ pub(crate) trait PassByValue: Sized {
///
/// `arg_out` must not be NULL and must be properly aligned and pointing to valid memory
/// of the size of CType.
unsafe fn to_arg_out(self, arg_out: *mut Self::CType) {
unsafe fn to_arg_out(val: Self::RustType, arg_out: *mut Self) {
debug_assert!(!arg_out.is_null());
// SAFETY:
// - arg_out is not NULL (promised by caller, asserted)
// - arg_out is properly aligned and points to valid memory (promised by caller)
unsafe { *arg_out = self.as_ctype() };
unsafe { *arg_out = Self::as_ctype(val) };
}
}