1use std::{ffi::CString, ptr};
2
3use crate::{check_status, sys};
4
5use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
6
7pub struct Symbol {
8 desc: Option<String>,
9 #[cfg(feature = "napi9")]
10 for_desc: Option<String>,
11}
12
13impl TypeName for Symbol {
14 fn type_name() -> &'static str {
15 "Symbol"
16 }
17
18 fn value_type() -> crate::ValueType {
19 crate::ValueType::Symbol
20 }
21}
22
23impl ValidateNapiValue for Symbol {}
24
25impl Symbol {
26 pub fn new(desc: String) -> Self {
27 Self {
28 desc: Some(desc),
29 #[cfg(feature = "napi9")]
30 for_desc: None,
31 }
32 }
33
34 pub fn identity() -> Self {
35 Self {
36 desc: None,
37 #[cfg(feature = "napi9")]
38 for_desc: None,
39 }
40 }
41
42 #[cfg(feature = "napi9")]
43 pub fn for_desc(desc: String) -> Self {
44 Self {
45 desc: None,
46 for_desc: Some(desc.to_owned()),
47 }
48 }
49}
50
51impl ToNapiValue for Symbol {
52 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
53 let mut symbol_value = ptr::null_mut();
54 #[cfg(feature = "napi9")]
55 if let Some(desc) = val.for_desc {
56 check_status!(
57 unsafe {
58 sys::node_api_symbol_for(env, desc.as_ptr().cast(), desc.len(), &mut symbol_value)
59 },
60 "Failed to call node_api_symbol_for"
61 )?;
62 return Ok(symbol_value);
63 }
64 check_status!(unsafe {
65 sys::napi_create_symbol(
66 env,
67 match val.desc {
68 Some(desc) => {
69 let mut desc_string = ptr::null_mut();
70 let desc_len = desc.len();
71 let desc_c_string = CString::new(desc)?;
72 check_status!(sys::napi_create_string_utf8(
73 env,
74 desc_c_string.as_ptr(),
75 desc_len,
76 &mut desc_string
77 ))?;
78 desc_string
79 }
80 None => ptr::null_mut(),
81 },
82 &mut symbol_value,
83 )
84 })?;
85 Ok(symbol_value)
86 }
87}
88
89impl FromNapiValue for Symbol {
90 unsafe fn from_napi_value(
91 _env: sys::napi_env,
92 _napi_val: sys::napi_value,
93 ) -> crate::Result<Self> {
94 Ok(Self {
95 desc: None,
96 #[cfg(feature = "napi9")]
97 for_desc: None,
98 })
99 }
100}
101