use super::types::rust_error_from_c_message;
use super::*;
use core::ffi::{c_char, c_void};
use core::ptr;
pub struct DeviceScope {
pub(crate) handle: *mut c_void,
}
impl DeviceScope {
pub fn default() -> Result<Self, Error> {
let mut handle = ptr::null_mut();
let mut error_msg: *const c_char = ptr::null();
let status = unsafe { szs_device_scope_init_default(&mut handle, &mut error_msg) };
match status {
Status::Success => Ok(Self { handle }),
err => Err(rust_error_from_c_message(err, error_msg)),
}
}
pub fn cpu_cores(cpu_cores: usize) -> Result<Self, Error> {
let mut handle = ptr::null_mut();
let mut error_msg: *const c_char = ptr::null();
let status = unsafe { szs_device_scope_init_cpu_cores(cpu_cores, &mut handle, &mut error_msg) };
match status {
Status::Success => Ok(Self { handle }),
err => Err(rust_error_from_c_message(err, error_msg)),
}
}
pub fn gpu_device(gpu_device: usize) -> Result<Self, Error> {
let mut handle = ptr::null_mut();
let mut error_msg: *const c_char = ptr::null();
let status = unsafe { szs_device_scope_init_gpu_device(gpu_device, &mut handle, &mut error_msg) };
match status {
Status::Success => Ok(Self { handle }),
err => Err(rust_error_from_c_message(err, error_msg)),
}
}
pub fn get_capabilities(&self) -> Result<Capability, Error> {
let mut capabilities: Capability = 0;
let mut error_msg: *const c_char = ptr::null();
let status = unsafe { szs_device_scope_get_capabilities(self.handle, &mut capabilities, &mut error_msg) };
match status {
Status::Success => Ok(capabilities),
err => Err(rust_error_from_c_message(err, error_msg)),
}
}
pub fn get_cpu_cores(&self) -> Result<usize, Error> {
let mut cpu_cores: usize = 0;
let mut error_msg: *const c_char = ptr::null();
let status = unsafe { szs_device_scope_get_cpu_cores(self.handle, &mut cpu_cores, &mut error_msg) };
match status {
Status::Success => Ok(cpu_cores),
err => Err(rust_error_from_c_message(err, error_msg)),
}
}
pub fn get_gpu_device(&self) -> Result<usize, Error> {
let mut gpu_device: usize = 0;
let mut error_msg: *const c_char = ptr::null();
let status = unsafe { szs_device_scope_get_gpu_device(self.handle, &mut gpu_device, &mut error_msg) };
match status {
Status::Success => Ok(gpu_device),
err => Err(rust_error_from_c_message(err, error_msg)),
}
}
pub fn is_gpu(&self) -> bool {
self.get_gpu_device().is_ok()
}
}
impl Drop for DeviceScope {
fn drop(&mut self) {
if !self.handle.is_null() {
unsafe { szs_device_scope_free(self.handle) };
}
}
}
unsafe impl Send for DeviceScope {}
unsafe impl Sync for DeviceScope {}
extern "C" {
fn szs_device_scope_init_default(scope: *mut *mut c_void, error_message: *mut *const c_char) -> Status;
fn szs_device_scope_init_cpu_cores(
cpu_cores: usize,
scope: *mut *mut c_void,
error_message: *mut *const c_char,
) -> Status;
fn szs_device_scope_init_gpu_device(
gpu_device: usize,
scope: *mut *mut c_void,
error_message: *mut *const c_char,
) -> Status;
fn szs_device_scope_get_capabilities(
scope: *mut c_void,
capabilities: *mut Capability,
error_message: *mut *const c_char,
) -> Status;
fn szs_device_scope_get_cpu_cores(
scope: *mut c_void,
cpu_cores: *mut usize,
error_message: *mut *const c_char,
) -> Status;
fn szs_device_scope_get_gpu_device(
scope: *mut c_void,
gpu_device: *mut usize,
error_message: *mut *const c_char,
) -> Status;
fn szs_device_scope_free(scope: *mut c_void);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn device_scope_creation() {
let default_device = DeviceScope::default();
match default_device {
Ok(device) => {
let _caps = device.get_capabilities();
println!("Default device capabilities: {:?}", _caps);
}
Err(e) => println!("Default device creation failed: {:?}", e),
}
let cpu_device = DeviceScope::cpu_cores(4);
match cpu_device {
Ok(device) => {
assert!(!device.is_gpu());
if let Ok(cores) = device.get_cpu_cores() {
assert_eq!(cores, 4);
}
}
Err(e) => println!("CPU device creation failed: {:?}", e),
}
let gpu_device = DeviceScope::gpu_device(0);
match gpu_device {
Ok(device) => {
assert!(device.is_gpu());
if let Ok(gpu_id) = device.get_gpu_device() {
assert_eq!(gpu_id, 0);
}
}
Err(e) => println!("GPU device creation failed (expected if no GPU): {:?}", e),
}
}
#[test]
fn device_scope_validation() {
let all_cores = DeviceScope::cpu_cores(0);
assert!(all_cores.is_ok(), "CPU cores 0 should mean all cores");
let single_core = DeviceScope::cpu_cores(1);
assert!(single_core.is_ok(), "Single core should be valid");
let multi_cores = DeviceScope::cpu_cores(4);
assert!(multi_cores.is_ok(), "Multiple cores should be valid");
}
#[test]
fn device_scope_invalid_gpu_id_does_not_panic() {
match DeviceScope::gpu_device(999) {
Ok(_) => println!("GPU device 999 unexpectedly available"),
Err(e) => println!("GPU device 999 correctly failed: {:?}", e),
}
}
}