napi/js_values/string/
mod.rs

1use std::marker::PhantomData;
2use std::mem;
3use std::ptr;
4
5use crate::{
6  bindgen_runtime::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue},
7  check_status, sys, Result, Value, ValueType,
8};
9
10pub use latin1::JsStringLatin1;
11pub use utf16::JsStringUtf16;
12pub use utf8::JsStringUtf8;
13
14use super::JsValue;
15
16mod latin1;
17mod utf16;
18mod utf8;
19
20#[derive(Clone, Copy)]
21pub struct JsString<'env>(pub(crate) Value, pub(crate) PhantomData<&'env ()>);
22
23impl TypeName for JsString<'_> {
24  fn type_name() -> &'static str {
25    "String"
26  }
27
28  fn value_type() -> crate::ValueType {
29    ValueType::String
30  }
31}
32
33impl ValidateNapiValue for JsString<'_> {}
34
35impl<'env> JsValue<'env> for JsString<'env> {
36  fn value(&self) -> Value {
37    self.0
38  }
39}
40
41impl FromNapiValue for JsString<'_> {
42  unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
43    Ok(JsString(
44      Value {
45        env,
46        value: napi_val,
47        value_type: ValueType::String,
48      },
49      PhantomData,
50    ))
51  }
52}
53
54impl ToNapiValue for &JsString<'_> {
55  unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
56    Ok(val.raw())
57  }
58}
59
60impl<'env> JsString<'env> {
61  #[cfg(feature = "serde-json")]
62  pub(crate) fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Self {
63    JsString(
64      Value {
65        env,
66        value,
67        value_type: ValueType::String,
68      },
69      PhantomData,
70    )
71  }
72
73  pub fn utf8_len(&self) -> Result<usize> {
74    let mut length = 0;
75    check_status!(unsafe {
76      sys::napi_get_value_string_utf8(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
77    })?;
78    Ok(length)
79  }
80
81  pub fn utf16_len(&self) -> Result<usize> {
82    let mut length = 0;
83    check_status!(unsafe {
84      sys::napi_get_value_string_utf16(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
85    })?;
86    Ok(length)
87  }
88
89  pub fn latin1_len(&self) -> Result<usize> {
90    let mut length = 0;
91    check_status!(unsafe {
92      sys::napi_get_value_string_latin1(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
93    })?;
94    Ok(length)
95  }
96
97  pub fn into_utf8(self) -> Result<JsStringUtf8<'env>> {
98    let mut written_char_count = 0;
99    let len = self.utf8_len()? + 1;
100    let mut result = Vec::with_capacity(len);
101    let buf_ptr = result.as_mut_ptr();
102    check_status!(unsafe {
103      sys::napi_get_value_string_utf8(
104        self.0.env,
105        self.0.value,
106        buf_ptr,
107        len,
108        &mut written_char_count,
109      )
110    })?;
111
112    mem::forget(result);
113
114    Ok(JsStringUtf8 {
115      inner: self,
116      buf: unsafe { Vec::from_raw_parts(buf_ptr.cast(), written_char_count, written_char_count) },
117    })
118  }
119
120  pub fn into_utf16(self) -> Result<JsStringUtf16<'env>> {
121    let mut written_char_count = 0usize;
122    let len = self.utf16_len()? + 1;
123    let mut result = vec![0; len];
124    let buf_ptr = result.as_mut_ptr();
125    check_status!(unsafe {
126      sys::napi_get_value_string_utf16(
127        self.0.env,
128        self.0.value,
129        buf_ptr,
130        len,
131        &mut written_char_count,
132      )
133    })?;
134
135    Ok(JsStringUtf16 {
136      inner: self,
137      buf: unsafe { std::slice::from_raw_parts(buf_ptr.cast(), len) },
138      _inner_buf: result,
139    })
140  }
141
142  pub fn into_latin1(self) -> Result<JsStringLatin1<'env>> {
143    let mut written_char_count = 0usize;
144    let len = self.latin1_len()? + 1;
145    let mut result = Vec::with_capacity(len);
146    let buf_ptr = result.as_mut_ptr();
147    check_status!(unsafe {
148      sys::napi_get_value_string_latin1(
149        self.0.env,
150        self.0.value,
151        buf_ptr,
152        len,
153        &mut written_char_count,
154      )
155    })?;
156
157    mem::forget(result);
158
159    Ok(JsStringLatin1 {
160      inner: self,
161      buf: unsafe { std::slice::from_raw_parts(buf_ptr.cast(), written_char_count) },
162      _inner_buf: unsafe {
163        Vec::from_raw_parts(buf_ptr.cast(), written_char_count, written_char_count)
164      },
165    })
166  }
167}