napi/js_values/
value.rs

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  /// Convert the value to an unknown
31  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  /// Coerce the value to a boolean
43  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}