libgir/analysis/
c_type.rs

1use log::trace;
2
3use crate::{env::Env, library::TypeId};
4
5pub fn rustify_pointers(c_type: &str) -> (String, String) {
6    let mut input = c_type.trim();
7    let leading_const = input.starts_with("const ");
8    if leading_const {
9        input = &input[6..];
10    }
11    let end = [
12        input.find(" const"),
13        input.find("*const"),
14        input.find('*'),
15        Some(input.len()),
16    ]
17    .iter()
18    .filter_map(|&x| x)
19    .min()
20    .unwrap();
21    let inner = input[..end].trim().into();
22
23    let mut ptrs: Vec<_> = input[end..]
24        .rsplit('*')
25        .skip(1)
26        .map(|s| {
27            if s.contains("const") {
28                "*const"
29            } else {
30                "*mut"
31            }
32        })
33        .collect();
34    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
35        *p = "*const";
36    }
37
38    let res = (ptrs.join(" "), inner);
39    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
40    res
41}
42
43pub fn is_mut_ptr(c_type: &str) -> bool {
44    let (ptr, _inner) = rustify_pointers(c_type);
45    ptr.find("*mut") == Some(0)
46}
47
48pub fn implements_c_type(env: &Env, tid: TypeId, c_type: &str) -> bool {
49    env.class_hierarchy
50        .supertypes(tid)
51        .iter()
52        .any(|&super_tid| env.library.type_(super_tid).get_glib_name() == Some(c_type))
53}
54
55#[cfg(test)]
56mod tests {
57    use super::rustify_pointers as rustify_ptr;
58
59    fn s(x: &str, y: &str) -> (String, String) {
60        (x.into(), y.into())
61    }
62
63    #[test]
64    fn rustify_pointers() {
65        assert_eq!(rustify_ptr("char"), s("", "char"));
66        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
67        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
68        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
69        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
70        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
71        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
72        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
73        assert_eq!(
74            rustify_ptr("const char* const*"),
75            s("*const *const", "char")
76        );
77        assert_eq!(
78            rustify_ptr("char const * const *"),
79            s("*const *const", "char")
80        );
81        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
82
83        assert_eq!(rustify_ptr("GtkWidget*"), s("*mut", "GtkWidget"));
84    }
85}