napi_calm_down/js_values/string/
mod.rs

1use std::mem;
2use std::ptr;
3
4use crate::bindgen_runtime::TypeName;
5use crate::bindgen_runtime::ValidateNapiValue;
6use crate::ValueType;
7use crate::{check_status, sys, Result, Value};
8
9pub use latin1::JsStringLatin1;
10pub use utf16::JsStringUtf16;
11pub use utf8::JsStringUtf8;
12
13mod latin1;
14mod utf16;
15mod utf8;
16
17#[derive(Clone, Copy)]
18pub struct JsString(pub(crate) Value);
19
20impl TypeName for JsString {
21  fn type_name() -> &'static str {
22    "String"
23  }
24
25  fn value_type() -> crate::ValueType {
26    ValueType::String
27  }
28}
29
30impl ValidateNapiValue for JsString {}
31
32impl JsString {
33  pub fn utf8_len(&self) -> Result<usize> {
34    let mut length = 0;
35    check_status!(unsafe {
36      sys::napi_get_value_string_utf8(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
37    })?;
38    Ok(length)
39  }
40
41  pub fn utf16_len(&self) -> Result<usize> {
42    let mut length = 0;
43    check_status!(unsafe {
44      sys::napi_get_value_string_utf16(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
45    })?;
46    Ok(length)
47  }
48
49  pub fn latin1_len(&self) -> Result<usize> {
50    let mut length = 0;
51    check_status!(unsafe {
52      sys::napi_get_value_string_latin1(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
53    })?;
54    Ok(length)
55  }
56
57  pub fn into_utf8(self) -> Result<JsStringUtf8> {
58    let mut written_char_count = 0;
59    let len = self.utf8_len()? + 1;
60    let mut result = Vec::with_capacity(len);
61    let buf_ptr = result.as_mut_ptr();
62    check_status!(unsafe {
63      sys::napi_get_value_string_utf8(
64        self.0.env,
65        self.0.value,
66        buf_ptr,
67        len,
68        &mut written_char_count,
69      )
70    })?;
71
72    // respect '\0' with js string, for example: `let hello = [a,'\0',b,'\0',c].join('')`
73    let mut result = mem::ManuallyDrop::new(result);
74    let buf_ptr = result.as_mut_ptr();
75    let bytes = unsafe { Vec::from_raw_parts(buf_ptr as *mut u8, written_char_count, len) };
76    Ok(JsStringUtf8 {
77      inner: self,
78      buf: bytes,
79    })
80  }
81
82  pub fn into_utf16(self) -> Result<JsStringUtf16> {
83    let mut written_char_count = 0usize;
84    let len = self.utf16_len()? + 1;
85    let mut result = vec![0; len];
86    let buf_ptr = result.as_mut_ptr();
87    check_status!(unsafe {
88      sys::napi_get_value_string_utf16(
89        self.0.env,
90        self.0.value,
91        buf_ptr,
92        len,
93        &mut written_char_count,
94      )
95    })?;
96
97    Ok(JsStringUtf16 {
98      inner: self,
99      buf: result,
100    })
101  }
102
103  pub fn into_latin1(self) -> Result<JsStringLatin1> {
104    let mut written_char_count = 0usize;
105    let len = self.latin1_len()? + 1;
106    let mut result = Vec::with_capacity(len);
107    let buf_ptr = result.as_mut_ptr();
108    check_status!(unsafe {
109      sys::napi_get_value_string_latin1(
110        self.0.env,
111        self.0.value,
112        buf_ptr,
113        len,
114        &mut written_char_count,
115      )
116    })?;
117
118    mem::forget(result);
119
120    Ok(JsStringLatin1 {
121      inner: self,
122      buf: mem::ManuallyDrop::new(unsafe {
123        Vec::from_raw_parts(buf_ptr as *mut _, written_char_count, written_char_count)
124      }),
125    })
126  }
127}