1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::slice::SliceInner;

pub const CXX_INCLUDE_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/include");
pub const CXX_HEADER_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/include/rust_types.hxx");
pub const CXX_HEADER_CONTENT: &str = include_str!("../include/rust_types.hxx");

#[allow(non_camel_case_types)]
#[cfg(feature = "libc")]
type c_char = libc::c_char;
#[allow(non_camel_case_types)]
#[cfg(not(feature = "libc"))]
type c_char = u8;

pub type COptionBox<T> = crate::OptionBox<T>;
pub type CBox<T> = COptionBox<T>;

pub type CSliceRef<T> = crate::SliceRef<T>;
pub type CBoxedSlice<T> = crate::BoxedSlice<T>;
pub type CByteSliceRef = crate::ByteSliceRef;

pub type CStrRef = crate::StrRef;

/// not related to [`std::ffi::CStr`] or [`std::ffi::CString`]
pub type CharStrRef = crate::SliceRef<c_char>;

impl CharStrRef {
    #[cfg(feature = "libc")]
    #[inline(always)]
    pub fn as_bytes(&self) -> &[u8] {
        let ptr = self.as_ptr();
        let len = self.len();
        unsafe { std::slice::from_raw_parts(ptr as *const _, len) }
    }
    #[cfg(not(feature = "libc"))]
    #[inline(always)]
    fn as_bytes(&self) -> &[u8] {
        self.as_ref()
    }

    #[inline(always)]
    pub fn to_str(&self) -> Result<&str, std::str::Utf8Error> {
        std::str::from_utf8(self.as_bytes())
    }

    #[inline(always)]
    pub fn unwrap_str(&self) -> &str {
        self.to_str().unwrap()
    }

    #[inline(always)]
    pub fn expect_str(&self, msg: &str) -> &str {
        self.to_str().expect(msg)
    }

    /// # Safety
    /// `self` must be a valid utf-8 string.
    #[inline(always)]
    pub unsafe fn into_rust_unchecked(self) -> crate::StrRef {
        let inner = self.0;
        crate::StrRef(SliceInner {
            ptr: inner.ptr as *mut _,
            len: inner.len,
        })
    }

    #[inline(always)]
    pub fn into_rust(self) -> Result<crate::StrRef, std::str::Utf8Error> {
        std::str::from_utf8(self.as_bytes())?;
        Ok(unsafe { self.into_rust_unchecked() })
    }
}

pub type CBoxedStr = crate::BoxedStr;

pub mod ffi {
    use super::*;

    #[export_name = "_rust_ffi_boxed_str_drop"]
    pub unsafe extern "C" fn boxed_str_drop(_value: CBoxedStr) {}

    #[export_name = "_rust_ffi_boxed_bytes_drop"]
    pub unsafe extern "C" fn boxed_bytes_drop(_slice: CBoxedSlice<u8>) {}
}