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)]
8pub struct LlamaBackendDevice {
9 pub index: usize,
10 pub name: String,
11 pub description: String,
12 pub backend: String,
13 pub memory_total: usize,
14 pub memory_free: usize,
15 pub device_type: LlamaBackendDeviceType,
16}
17
18fn cstr_to_string(ptr: *const c_char) -> String {
19 if ptr.is_null() {
20 String::new()
21 } else {
22 unsafe { std::ffi::CStr::from_ptr(ptr) }
23 .to_string_lossy()
24 .to_string()
25 }
26}
27
28#[must_use]
29pub fn list_llama_ggml_backend_devices() -> Vec<LlamaBackendDevice> {
30 let mut devices = Vec::new();
31 let device_count = unsafe { llama_cpp_bindings_sys::ggml_backend_dev_count() };
32
33 for device_index in 0..device_count {
34 let dev = unsafe { llama_cpp_bindings_sys::ggml_backend_dev_get(device_index) };
35 let props = unsafe {
36 let mut props = std::mem::zeroed();
37 llama_cpp_bindings_sys::ggml_backend_dev_get_props(dev, &raw mut props);
38 props
39 };
40 let name = cstr_to_string(props.name);
41 let description = cstr_to_string(props.description);
42 let backend_reg = unsafe { llama_cpp_bindings_sys::ggml_backend_dev_backend_reg(dev) };
43 let backend_name = unsafe { llama_cpp_bindings_sys::ggml_backend_reg_name(backend_reg) };
44 let backend = cstr_to_string(backend_name);
45 let memory_total = props.memory_total;
46 let memory_free = props.memory_free;
47 let device_type = device_type_from_raw(props.type_);
48 devices.push(LlamaBackendDevice {
49 index: device_index,
50 name,
51 description,
52 backend,
53 memory_total,
54 memory_free,
55 device_type,
56 });
57 }
58
59 devices
60}
61
62#[cfg(test)]
63mod tests {
64 use super::{cstr_to_string, list_llama_ggml_backend_devices};
65
66 #[test]
67 fn cstr_to_string_with_null_returns_empty() {
68 let result = cstr_to_string(std::ptr::null());
69
70 assert_eq!(result, "");
71 }
72
73 #[test]
74 fn cstr_to_string_with_valid_ptr() {
75 let result = cstr_to_string(c"hello".as_ptr());
76
77 assert_eq!(result, "hello");
78 }
79
80 #[test]
81 fn list_devices_returns_at_least_one() {
82 #[cfg(feature = "dynamic-backends")]
83 crate::load_backends::load_backends().unwrap();
84
85 let devices = list_llama_ggml_backend_devices();
86 assert!(!devices.is_empty());
87 assert_eq!(devices[0].index, 0);
88 assert!(!devices[0].name.is_empty());
89 }
90}