storage-bindings 0.4.4

Rust bindings for Storage, the Decentralized Durability Engine
//! FFI bindings for the libstorage C library
//!
//! This module contains the low-level bindings generated by bindgen
//! and provides safe wrappers around the C functions.

// Include the generated bindings in a module to suppress warnings
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
mod generated {
    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}

// Re-export all the generated bindings
pub use generated::*;

// Send-safe wrapper for raw pointers
pub mod send_safe;
pub use send_safe::{SendSafeCString, SendSafePtr};

use libc::c_char;
use std::ffi::CStr;
use std::str::Utf8Error;

/// Convert a C string to a Rust string
///
/// # Safety
///
/// The `ptr` must be either:
/// - A valid pointer to a null-terminated C string
/// - A null pointer (which will return an empty string)
///
/// The memory pointed to by `ptr` must remain valid for the duration of this call.
pub unsafe fn c_str_to_string(ptr: *const c_char) -> Result<String, Utf8Error> {
    if ptr.is_null() {
        return Ok(String::new());
    }

    let c_str = CStr::from_ptr(ptr);
    c_str.to_str().map(|s| s.to_string())
}

/// Convert a Rust string to a C string (Send-safe)
pub fn string_to_c_string(s: &str) -> SendSafeCString {
    SendSafeCString::new(s)
}

/// Callback return codes
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CallbackReturn {
    Ok = 0,
    Error = 1,
    Progress = 3,
}

impl From<i32> for CallbackReturn {
    fn from(value: i32) -> Self {
        match value {
            0 => CallbackReturn::Ok,
            1 => CallbackReturn::Error,
            3 => CallbackReturn::Progress,
            _ => CallbackReturn::Error,
        }
    }
}

/// Callback function type - available from generated bindings
// The StorageCallback type alias is already available from the generated bindings
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_c_str_conversion() {
        let rust_str = "Hello, World!";
        let c_str = string_to_c_string(rust_str);

        unsafe {
            let converted = c_str_to_string(c_str.as_ptr()).unwrap();
            assert_eq!(rust_str, converted);
        }
    }
}