Skip to main content

fui/
host_services.rs

1use crate::event;
2
3pub fn host_service_result_buffer_ptr() -> *mut u8 {
4    event::__fui_text_buffer() as *mut u8
5}
6
7pub fn host_service_result_buffer_size() -> u32 {
8    event::__fui_text_buffer_size()
9}
10
11fn assert_result_byte_length(result_len: u32, import_name: &str) {
12    let capacity = host_service_result_buffer_size();
13    if result_len > capacity {
14        panic!(
15            "Host service {} returned {} bytes but the shared result buffer only holds {}.",
16            import_name, result_len, capacity
17        );
18    }
19}
20
21pub fn decode_host_service_string_result(
22    result_ptr: *mut u8,
23    result_len: u32,
24    import_name: &str,
25) -> String {
26    assert_result_byte_length(result_len, import_name);
27    if result_len == 0 {
28        return String::new();
29    }
30    let bytes = unsafe { std::slice::from_raw_parts(result_ptr as *const u8, result_len as usize) };
31    String::from_utf8_lossy(bytes).into_owned()
32}
33
34pub fn decode_host_service_bytes_result(
35    result_ptr: *mut u8,
36    result_len: u32,
37    import_name: &str,
38) -> Vec<u8> {
39    assert_result_byte_length(result_len, import_name);
40    if result_len == 0 {
41        return Vec::new();
42    }
43    unsafe { std::slice::from_raw_parts(result_ptr as *const u8, result_len as usize) }.to_vec()
44}
45
46pub fn decode_host_service_i32_array_result(
47    result_ptr: *mut u8,
48    result_len: u32,
49    import_name: &str,
50) -> Vec<i32> {
51    assert_result_byte_length(result_len, import_name);
52    assert_eq!(
53        result_len & 3,
54        0,
55        "Host service {} returned misaligned i32 array byte length.",
56        import_name
57    );
58    if result_len == 0 {
59        return Vec::new();
60    }
61    unsafe {
62        std::slice::from_raw_parts(result_ptr as *const i32, (result_len >> 2) as usize).to_vec()
63    }
64}
65
66pub fn decode_host_service_u32_array_result(
67    result_ptr: *mut u8,
68    result_len: u32,
69    import_name: &str,
70) -> Vec<u32> {
71    assert_result_byte_length(result_len, import_name);
72    assert_eq!(
73        result_len & 3,
74        0,
75        "Host service {} returned misaligned u32 array byte length.",
76        import_name
77    );
78    if result_len == 0 {
79        return Vec::new();
80    }
81    unsafe {
82        std::slice::from_raw_parts(result_ptr as *const u32, (result_len >> 2) as usize).to_vec()
83    }
84}
85
86pub fn decode_host_service_i64_array_result(
87    result_ptr: *mut u8,
88    result_len: u32,
89    import_name: &str,
90) -> Vec<i64> {
91    assert_result_byte_length(result_len, import_name);
92    assert_eq!(
93        result_len & 7,
94        0,
95        "Host service {} returned misaligned i64 array byte length.",
96        import_name
97    );
98    if result_len == 0 {
99        return Vec::new();
100    }
101    unsafe {
102        std::slice::from_raw_parts(result_ptr as *const i64, (result_len >> 3) as usize).to_vec()
103    }
104}
105
106pub fn decode_host_service_u64_array_result(
107    result_ptr: *mut u8,
108    result_len: u32,
109    import_name: &str,
110) -> Vec<u64> {
111    assert_result_byte_length(result_len, import_name);
112    assert_eq!(
113        result_len & 7,
114        0,
115        "Host service {} returned misaligned u64 array byte length.",
116        import_name
117    );
118    if result_len == 0 {
119        return Vec::new();
120    }
121    unsafe {
122        std::slice::from_raw_parts(result_ptr as *const u64, (result_len >> 3) as usize).to_vec()
123    }
124}
125
126pub fn decode_host_service_f64_array_result(
127    result_ptr: *mut u8,
128    result_len: u32,
129    import_name: &str,
130) -> Vec<f64> {
131    assert_result_byte_length(result_len, import_name);
132    assert_eq!(
133        result_len & 7,
134        0,
135        "Host service {} returned misaligned f64 array byte length.",
136        import_name
137    );
138    if result_len == 0 {
139        return Vec::new();
140    }
141    unsafe {
142        std::slice::from_raw_parts(result_ptr as *const f64, (result_len >> 3) as usize).to_vec()
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use super::*;
149
150    #[test]
151    fn decodes_string_result_from_shared_text_buffer() {
152        let ptr = host_service_result_buffer_ptr();
153        let bytes = b"demo-host";
154        unsafe {
155            std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr, bytes.len());
156        }
157        assert_eq!(
158            decode_host_service_string_result(ptr, bytes.len() as u32, "demo_service"),
159            "demo-host"
160        );
161    }
162}