llama_cpp_bindings/
llama_backend_device.rs1use std::ffi::c_char;
2
3use crate::llama_backend_device_type::device_type_from_raw;
4
5pub use crate::llama_backend_device_type::LlamaBackendDeviceType;
6
7#[derive(Debug, Clone)]
11pub struct LlamaBackendDevice {
12 pub index: usize,
16 pub name: String,
18 pub description: String,
20 pub backend: String,
22 pub memory_total: usize,
24 pub memory_free: usize,
26 pub device_type: LlamaBackendDeviceType,
28}
29
30fn cstr_to_string(ptr: *const c_char) -> String {
31 if ptr.is_null() {
32 String::new()
33 } else {
34 unsafe { std::ffi::CStr::from_ptr(ptr) }
35 .to_string_lossy()
36 .to_string()
37 }
38}
39
40#[must_use]
42pub fn list_llama_ggml_backend_devices() -> Vec<LlamaBackendDevice> {
43 let mut devices = Vec::new();
44 let device_count = unsafe { llama_cpp_bindings_sys::ggml_backend_dev_count() };
45
46 for device_index in 0..device_count {
47 let dev = unsafe { llama_cpp_bindings_sys::ggml_backend_dev_get(device_index) };
48 let props = unsafe {
49 let mut props = std::mem::zeroed();
50 llama_cpp_bindings_sys::ggml_backend_dev_get_props(dev, &raw mut props);
51 props
52 };
53 let name = cstr_to_string(props.name);
54 let description = cstr_to_string(props.description);
55 let backend_reg = unsafe { llama_cpp_bindings_sys::ggml_backend_dev_backend_reg(dev) };
56 let backend_name = unsafe { llama_cpp_bindings_sys::ggml_backend_reg_name(backend_reg) };
57 let backend = cstr_to_string(backend_name);
58 let memory_total = props.memory_total;
59 let memory_free = props.memory_free;
60 let device_type = device_type_from_raw(props.type_);
61 devices.push(LlamaBackendDevice {
62 index: device_index,
63 name,
64 description,
65 backend,
66 memory_total,
67 memory_free,
68 device_type,
69 });
70 }
71
72 devices
73}
74
75#[cfg(test)]
76mod tests {
77 use super::{cstr_to_string, list_llama_ggml_backend_devices};
78
79 #[test]
80 fn cstr_to_string_with_null_returns_empty() {
81 let result = cstr_to_string(std::ptr::null());
82
83 assert_eq!(result, "");
84 }
85
86 #[test]
87 fn cstr_to_string_with_valid_ptr() {
88 let result = cstr_to_string(c"hello".as_ptr());
89
90 assert_eq!(result, "hello");
91 }
92
93 #[test]
94 fn list_devices_returns_at_least_one() {
95 #[cfg(feature = "dynamic-backends")]
96 crate::load_backends::load_backends().unwrap();
97
98 let devices = list_llama_ggml_backend_devices();
99 assert!(!devices.is_empty());
100 assert_eq!(devices[0].index, 0);
101 assert!(!devices[0].name.is_empty());
102 }
103}