1use std::fmt::Display;
3
4use super::*;
5
6#[allow(clippy::not_unsafe_ptr_arg_deref)]
8pub fn get_str_from_pointer<'a>(ptr: *const c_char) -> Option<&'a str> {
9 if ptr.is_null() {
10 return None;
11 }
12
13 let slice = unsafe { CStr::from_ptr(ptr) };
14
15 std::str::from_utf8(slice.to_bytes()).ok()
16}
17
18pub fn get_string_from_pointer(ptr: *const c_char) -> Option<String> {
20 get_str_from_pointer(ptr).map(|s| s.to_owned())
21}
22
23pub fn get_path_from_pointer<'a>(ptr: *const c_char) -> Option<&'a Path> {
25 if ptr.is_null() {
26 return None;
27 }
28
29 let slice = unsafe { CStr::from_ptr(ptr as *const _) };
30
31 cfg_if::cfg_if! {
32 if #[cfg(target_family = "unix")] {
33 use std::os::unix::ffi::OsStrExt;
34 let oss = OsStr::from_bytes(slice.to_bytes());
35 let path: &Path = oss.as_ref();
36 Some(path)
37 }
38 else {
39 let s = std::str::from_utf8(slice.to_bytes()).expect("valid UTF-8");
40 let path: &Path = s.as_ref();
41 Some(path)
42 }
43 }
44}
45
46pub fn get_path_buf_from_pointer(ptr: *mut c_char) -> Option<PathBuf> {
48 get_str_from_pointer(ptr).map(PathBuf::from)
49}
50
51#[derive(Debug, Copy, Clone)]
52pub struct Version {
53 major: u16,
54 minor: u16,
55 patch: u16,
56}
57
58impl Version {
59 pub const fn new(major: u16, minor: u16, patch: u16) -> Self {
60 if patch > 0xfff {
61 panic!("Invalid patch level");
62 }
63
64 if minor > 0x3ff {
65 panic!("Invalid minor level");
66 }
67
68 if major > 0x3ff {
69 panic!("Invalid major level");
70 }
71
72 Self {
73 major,
74 minor,
75 patch,
76 }
77 }
78
79 pub const fn from_u32(version: u32) -> Self {
80 Self {
82 major: ((version >> 22) & 0x3ff) as u16,
83 minor: ((version >> 12) & 0x3ff) as u16,
84 patch: (version & 0xfff) as u16,
85 }
86 }
87
88 pub const fn to_u32(self) -> u32 {
89 ((self.major as u32) << 22) | ((self.minor as u32) << 12) | (self.patch as u32)
91 }
92}
93
94impl Display for Version {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
97 }
98}