rquickjs_extra_utils/ffi/
c_string.rs1use 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 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}