napi/js_values/string/
mod.rs1use 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}