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}
128