rquickjs_extra_utils/ffi/
c_string.rs

1use std::mem;
2use std::{ffi::c_char, slice, str};
3
4use rquickjs::{Error, Exception, Result, String, Value, qjs};
5
6#[derive(Debug)]
7pub struct CString<'js> {
8    ptr: *const c_char,
9    len: usize,
10    value: Value<'js>,
11}
12
13#[allow(dead_code)]
14impl<'js> CString<'js> {
15    pub fn from_string(string: String<'js>) -> Result<Self> {
16        let mut len = mem::MaybeUninit::uninit();
17        let ptr = unsafe {
18            qjs::JS_ToCStringLen(
19                string.ctx().as_raw().as_ptr(),
20                len.as_mut_ptr(),
21                string.as_raw(),
22            )
23        };
24        if ptr.is_null() {
25            // Might not ever happen but I am not 100% sure
26            // so just incase check it.
27            return Err(Error::Unknown);
28        }
29        let len = unsafe { len.assume_init() };
30        Ok(Self {
31            ptr,
32            len,
33            value: string.into_value(),
34        })
35    }
36
37    pub fn as_ptr(&self) -> *const c_char {
38        self.ptr
39    }
40
41    pub fn len(&self) -> usize {
42        self.len
43    }
44
45    pub fn is_empty(&self) -> bool {
46        self.len == 0
47    }
48
49    pub fn as_str(&self) -> Result<&str> {
50        let bytes = unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) };
51        str::from_utf8(bytes)
52            .map_err(|_| Exception::throw_message(self.value.ctx(), "Invalid UTF-8"))
53    }
54}
55
56impl Drop for CString<'_> {
57    fn drop(&mut self) {
58        unsafe { qjs::JS_FreeCString(self.value.ctx().as_raw().as_ptr(), self.ptr) };
59    }
60}