ferroui_vulkan/unmanaged_interop/
utf8_buffer_array.rs1use std::ffi::{c_char, CString};
2
3pub struct Utf8BufferArray {
7 buffers: Vec<CString>,
8 buffer_array: Vec<*const c_char>,
9}
10
11impl Utf8BufferArray {
12 pub fn new<S: AsRef<str>>(strings: impl IntoIterator<Item = S>) -> Self {
15 let buffers: Vec<CString> = strings
16 .into_iter()
17 .map(|s| {
18 let s = s.as_ref();
19 let end = s.find('\0').unwrap_or(s.len());
20 CString::new(&s[..end]).expect("the string was cut at its first zero character")
21 })
22 .collect();
23 let buffer_array = buffers.iter().map(|buffer| buffer.as_ptr()).collect();
26 Self { buffers, buffer_array }
27 }
28
29 pub fn as_slice(&self) -> &[*const c_char] {
31 &self.buffer_array
32 }
33
34 pub fn count(&self) -> i32 {
36 self.buffers.len() as i32
37 }
38
39 pub fn u_count(&self) -> u32 {
41 self.count() as u32
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use std::ffi::CStr;
49
50 #[test]
51 fn the_array_points_at_zero_terminated_copies() {
52 let array = Utf8BufferArray::new(["VK_KHR_surface", "VK_KHR_xlib_surface", "zażółć"]);
53 assert_eq!(array.count(), 3);
54 assert_eq!(array.u_count(), 3);
55 let read: Vec<String> = array
56 .as_slice()
57 .iter()
58 .map(|pointer| unsafe { CStr::from_ptr(*pointer) }.to_str().unwrap().to_string())
60 .collect();
61 assert_eq!(read, ["VK_KHR_surface", "VK_KHR_xlib_surface", "zażółć"]);
62 }
63
64 #[test]
65 fn an_empty_list_is_an_empty_array() {
66 let array = Utf8BufferArray::new(Vec::<String>::new());
67 assert_eq!(array.count(), 0);
68 assert!(array.as_slice().is_empty());
69 }
70
71 #[test]
72 fn a_string_ends_at_its_first_zero_character() {
73 let array = Utf8BufferArray::new(["ab\0cd"]);
74 let read = unsafe { CStr::from_ptr(array.as_slice()[0]) };
76 assert_eq!(read.to_str().unwrap(), "ab");
77 }
78}