1use std::fmt::{self, Display};
2use std::ptr;
3
4use crate::bindgen_runtime::EscapableHandleScope;
5use crate::{
6 bindgen_runtime::{FromNapiValue, Object, Unknown},
7 {check_status, sys, JsNumber, JsString, Result, ValueType},
8};
9
10#[derive(Debug, Clone, Copy)]
11pub struct Value {
12 pub env: sys::napi_env,
13 pub value: sys::napi_value,
14 pub value_type: ValueType,
15}
16
17impl Display for Value {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 write!(f, "Value({:?})", self.value_type)
20 }
21}
22
23pub trait JsValue<'env>: Sized + FromNapiValue {
24 fn value(&self) -> Value;
25
26 fn raw(&self) -> sys::napi_value {
27 self.value().value
28 }
29
30 fn to_unknown(&self) -> Unknown<'env> {
32 Unknown(
33 Value {
34 env: self.value().env,
35 value: self.value().value,
36 value_type: ValueType::Unknown,
37 },
38 std::marker::PhantomData,
39 )
40 }
41
42 fn coerce_to_bool(&self) -> Result<bool> {
44 let mut new_raw_value = ptr::null_mut();
45 let env = self.value().env;
46 check_status!(unsafe {
47 sys::napi_coerce_to_bool(env, self.value().value, &mut new_raw_value)
48 })?;
49 unsafe { bool::from_napi_value(env, new_raw_value) }
50 }
51
52 fn coerce_to_number(&self) -> Result<JsNumber<'_>> {
53 let mut new_raw_value = ptr::null_mut();
54 let env = self.value().env;
55 check_status!(unsafe {
56 sys::napi_coerce_to_number(env, self.value().value, &mut new_raw_value)
57 })?;
58 Ok(JsNumber(
59 Value {
60 env,
61 value: new_raw_value,
62 value_type: ValueType::Number,
63 },
64 std::marker::PhantomData,
65 ))
66 }
67
68 fn coerce_to_string(&self) -> Result<JsString<'_>> {
69 let mut new_raw_value = ptr::null_mut();
70 let env = self.value().env;
71 check_status!(unsafe {
72 sys::napi_coerce_to_string(env, self.value().value, &mut new_raw_value)
73 })?;
74 Ok(JsString(
75 Value {
76 env,
77 value: new_raw_value,
78 value_type: ValueType::String,
79 },
80 std::marker::PhantomData,
81 ))
82 }
83
84 fn coerce_to_object(&self) -> Result<Object<'env>> {
85 let mut new_raw_value = ptr::null_mut();
86 let env = self.value().env;
87 check_status!(unsafe {
88 sys::napi_coerce_to_object(env, self.value().value, &mut new_raw_value)
89 })?;
90 Ok(Object::from_raw(env, new_raw_value))
91 }
92
93 #[cfg(feature = "napi5")]
94 fn is_date(&self) -> Result<bool> {
95 let mut is_date = true;
96 let env = self.value().env;
97 check_status!(unsafe { sys::napi_is_date(env, self.value().value, &mut is_date) })?;
98 Ok(is_date)
99 }
100
101 fn is_promise(&self) -> Result<bool> {
102 let mut is_promise = true;
103 let env = self.value().env;
104 check_status!(unsafe { sys::napi_is_promise(env, self.value().value, &mut is_promise) })?;
105 Ok(is_promise)
106 }
107
108 fn is_error(&self) -> Result<bool> {
109 let mut result = false;
110 let env = self.value().env;
111 check_status!(unsafe { sys::napi_is_error(env, self.value().value, &mut result) })?;
112 Ok(result)
113 }
114
115 fn is_typedarray(&self) -> Result<bool> {
116 let mut result = false;
117 let env = self.value().env;
118 check_status!(unsafe { sys::napi_is_typedarray(env, self.value().value, &mut result) })?;
119 Ok(result)
120 }
121
122 fn is_dataview(&self) -> Result<bool> {
123 let mut result = false;
124 let env = self.value().env;
125 check_status!(unsafe { sys::napi_is_dataview(env, self.value().value, &mut result) })?;
126 Ok(result)
127 }
128
129 fn is_array(&self) -> Result<bool> {
130 let mut is_array = false;
131 let env = self.value().env;
132 check_status!(unsafe { sys::napi_is_array(env, self.value().value, &mut is_array) })?;
133 Ok(is_array)
134 }
135
136 fn is_buffer(&self) -> Result<bool> {
137 let mut is_buffer = false;
138 let env = self.value().env;
139 check_status!(unsafe { sys::napi_is_buffer(env, self.value().value, &mut is_buffer) })?;
140 Ok(is_buffer)
141 }
142
143 fn is_arraybuffer(&self) -> Result<bool> {
144 let mut is_buffer = false;
145 let env = self.value().env;
146 check_status!(unsafe { sys::napi_is_arraybuffer(env, self.value().value, &mut is_buffer) })?;
147 Ok(is_buffer)
148 }
149
150 fn instanceof<'c, Constructor>(&self, constructor: Constructor) -> Result<bool>
151 where
152 Constructor: JsValue<'c>,
153 {
154 let mut result = false;
155 let env = self.value().env;
156 check_status!(unsafe {
157 sys::napi_instanceof(env, self.value().value, constructor.raw(), &mut result)
158 })?;
159 Ok(result)
160 }
161
162 fn escape<'scope, E: JsValue<'scope> + FromNapiValue>(
163 &self,
164 escapable_handle_scope: EscapableHandleScope<'scope>,
165 ) -> Result<E> {
166 let mut result = ptr::null_mut();
167 unsafe {
168 sys::napi_escape_handle(
169 escapable_handle_scope.env,
170 escapable_handle_scope.scope,
171 self.raw(),
172 &mut result,
173 )
174 };
175 unsafe { <E as FromNapiValue>::from_napi_value(self.value().env, result) }
176 }
177}