1use std::{
4 ffi::{CStr, OsStr, c_char},
5 iter,
6 os::windows::prelude::OsStrExt,
7 slice,
8};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[repr(transparent)]
13pub struct Share<T>(T);
14
15impl<T> Share<T> {
16 pub unsafe fn new(value: T) -> Self {
18 Self(value)
19 }
20
21 pub unsafe fn get(&self) -> &T {
25 &self.0
26 }
27}
28
29unsafe impl<T> Sync for Share<T> {}
30
31unsafe impl<T> Send for Share<T> {}
32
33#[inline]
35pub unsafe fn str_from_cstr<'a>(ptr: *const c_char) -> Option<&'a str> {
36 if ptr.is_null() {
37 None
38 } else {
39 unsafe { CStr::from_ptr(ptr) }.to_str().ok()
40 }
41}
42
43#[inline]
47#[allow(dead_code)]
48pub unsafe fn str_from_cstr_len<'a>(ptr: *const c_char, len: u64) -> &'a str {
49 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len as usize) };
50 str::from_utf8(slice).expect("cstr with invalid utf8")
51}
52
53#[inline]
55pub fn strip_account_prefix(account_name: &str) -> &str {
56 account_name.strip_prefix(':').unwrap_or(account_name)
57}
58
59#[inline]
61pub fn str_to_wide(string: impl AsRef<str>) -> Vec<u16> {
62 OsStr::new(string.as_ref())
63 .encode_wide()
64 .chain(iter::once(0))
65 .collect()
66}
67
68macro_rules! abi {
70 ( $( $vis:vis type $name:ident = unsafe extern fn( $( $args:tt )* ) $( -> $ret:ty )? ; )* ) => {
71 $(
72 #[cfg(feature = "unwind")]
73 $vis type $name = unsafe extern "C-unwind" fn( $( $args )* ) $( -> $ret )?;
74
75 #[cfg(not(feature = "unwind"))]
76 $vis type $name = unsafe extern "C" fn( $( $args )* ) $( -> $ret )?;
77 )*
78 };
79}
80
81pub(crate) use abi;