use crate::{ Array, ArrayBuffer, BigInt, Boolean, Buffer, DataView, Date, Env, Error, External, Function, Null, Number, Object, Result, String, Symbol, TypedArray, Undefined, Value, }; use num::{FromPrimitive, ToPrimitive}; #[allow(clippy::wrong_self_convention, clippy::upper_case_acronyms)] pub trait IntoNodeApi<'a>: 'a { fn into_node_api(self, env: Env<'a>) -> Result>; } #[allow(clippy::wrong_self_convention, clippy::upper_case_acronyms)] pub trait FromNodeAPI<'a>: 'a + Sized { fn from_node_api(value: Value<'a>) -> Result; } impl<'a> IntoNodeApi<'a> for () { fn into_node_api(self, env: Env<'a>) -> Result> { Ok(Null::new(env)?.value()) } } impl<'a> FromNodeAPI<'a> for () { fn from_node_api(value: Value<'a>) -> Result { value.as_null()?; Ok(()) } } impl<'a> IntoNodeApi<'a> for bool { fn into_node_api(self, env: Env<'a>) -> Result> { Ok(Boolean::new(env, self)?.value()) } } impl<'a> FromNodeAPI<'a> for bool { fn from_node_api(value: Value<'a>) -> Result { let value = value.as_boolean()?; let value = value.get()?; Ok(value) } } macro_rules! impl_to_from_for_number_type { ($ty:ty) => { impl<'a> IntoNodeApi<'a> for $ty { fn into_node_api(self, env: Env<'a>) -> Result> { let value = <$ty>::to_f64(&self).ok_or_else(|| Error::message("number out of bounds"))?; let number = Number::new(env, value)?; Ok(number.value()) } } impl<'a> FromNodeAPI<'a> for $ty { fn from_node_api(value: Value<'a>) -> Result { let number = value.as_number()?; let value = number.get()?; let value = <$ty>::from_f64(value).ok_or_else(|| Error::message("number out of bounds"))?; Ok(value) } } }; } impl_to_from_for_number_type!(usize); impl_to_from_for_number_type!(u8); impl_to_from_for_number_type!(u16); impl_to_from_for_number_type!(u32); impl_to_from_for_number_type!(u64); impl_to_from_for_number_type!(isize); impl_to_from_for_number_type!(i8); impl_to_from_for_number_type!(i16); impl_to_from_for_number_type!(i32); impl_to_from_for_number_type!(i64); impl_to_from_for_number_type!(f32); impl_to_from_for_number_type!(f64); impl<'a> IntoNodeApi<'a> for char { fn into_node_api(self, env: Env<'a>) -> Result> { Ok(String::new(env, &self.to_string())?.value()) } } impl<'a> FromNodeAPI<'a> for char { fn from_node_api(value: Value<'a>) -> Result { Ok(value.as_string()?.get()?.chars().next().unwrap()) } } impl<'a> IntoNodeApi<'a> for &'a str { fn into_node_api(self, env: Env<'a>) -> Result> { Ok(String::new(env, self)?.value()) } } impl<'a> IntoNodeApi<'a> for std::string::String { fn into_node_api(self, env: Env<'a>) -> Result> { Ok(String::new(env, self.as_str())?.value()) } } impl<'a> FromNodeAPI<'a> for std::string::String { fn from_node_api(value: Value<'a>) -> Result { value.as_string()?.get() } } impl<'a, T> IntoNodeApi<'a> for Option where T: IntoNodeApi<'a>, { fn into_node_api(self, env: Env<'a>) -> Result> { match self { None => Ok(Null::new(env)?.value()), Some(value) => Ok(value.into_node_api(env)?), } } } impl<'a, T> FromNodeAPI<'a> for Option where T: FromNodeAPI<'a>, { fn from_node_api(value: Value<'a>) -> Result { if value.as_null().is_ok() || value.as_undefined().is_ok() { Ok(None) } else { Ok(Some(T::from_node_api(value)?)) } } } impl<'a, T> IntoNodeApi<'a> for Vec where T: IntoNodeApi<'a>, { fn into_node_api(self, env: Env<'a>) -> Result> { let mut array = Array::new(env)?; for (i, value) in self.into_iter().enumerate() { array.set(i, value.into_node_api(env)?)?; } Ok(array.value()) } } impl<'a, T> FromNodeAPI<'a> for Vec where T: FromNodeAPI<'a>, { fn from_node_api(value: Value<'a>) -> Result { let value = value.as_array()?; let mut vec = Vec::with_capacity(value.size()?); for value in value.iter()? { vec.push(T::from_node_api(value?)?); } Ok(vec) } } impl<'a> IntoNodeApi<'a> for Value<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self) } } impl<'a> FromNodeAPI<'a> for Value<'a> { fn from_node_api(value: Value<'a>) -> Result { Ok(value) } } impl<'a> IntoNodeApi<'a> for Array<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Array<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_array() } } impl<'a> IntoNodeApi<'a> for ArrayBuffer<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for ArrayBuffer<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_arraybuffer() } } impl<'a> IntoNodeApi<'a> for BigInt<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for BigInt<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_bigint() } } impl<'a> IntoNodeApi<'a> for Boolean<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Boolean<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_boolean() } } impl<'a> IntoNodeApi<'a> for Buffer<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Buffer<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_buffer() } } impl<'a> IntoNodeApi<'a> for DataView<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a, 'b: 'a> FromNodeAPI<'a> for DataView<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_dataview() } } impl<'a> IntoNodeApi<'a> for Date<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Date<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_date() } } impl<'a, T: 'a> IntoNodeApi<'a> for External<'a, T> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a, T: 'a> FromNodeAPI<'a> for External<'a, T> { fn from_node_api(value: Value<'a>) -> Result { value.as_external() } } impl<'a> IntoNodeApi<'a> for Function<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Function<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_function() } } impl<'a> IntoNodeApi<'a> for Null<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Null<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_null() } } impl<'a> IntoNodeApi<'a> for Number<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Number<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_number() } } impl<'a> IntoNodeApi<'a> for Object<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Object<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_object() } } impl<'a> IntoNodeApi<'a> for String<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for String<'a> { fn from_node_api(value: Value<'a>) -> Result { let value = value.as_string()?; Ok(value) } } impl<'a> IntoNodeApi<'a> for Symbol<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Symbol<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_symbol() } } impl<'a> IntoNodeApi<'a> for TypedArray<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for TypedArray<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_typedarray() } } impl<'a> IntoNodeApi<'a> for Undefined<'a> { fn into_node_api(self, _env: Env<'a>) -> Result> { Ok(self.value()) } } impl<'a> FromNodeAPI<'a> for Undefined<'a> { fn from_node_api(value: Value<'a>) -> Result { value.as_undefined() } }