node_api 0.5.0

Write Node.js native addons with Node-API in Rust.
Documentation
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<Value<'a>>;
}

#[allow(clippy::wrong_self_convention, clippy::upper_case_acronyms)]
pub trait FromNodeAPI<'a>: 'a + Sized {
	fn from_node_api(value: Value<'a>) -> Result<Self>;
}

impl<'a> IntoNodeApi<'a> for () {
	fn into_node_api(self, env: Env<'a>) -> Result<Value<'a>> {
		Ok(Null::new(env)?.value())
	}
}

impl<'a> FromNodeAPI<'a> for () {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_null()?;
		Ok(())
	}
}

impl<'a> IntoNodeApi<'a> for bool {
	fn into_node_api(self, env: Env<'a>) -> Result<Value<'a>> {
		Ok(Boolean::new(env, self)?.value())
	}
}

impl<'a> FromNodeAPI<'a> for bool {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		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<Value<'a>> {
				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<Self> {
				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<Value<'a>> {
		Ok(String::new(env, &self.to_string())?.value())
	}
}

impl<'a> FromNodeAPI<'a> for char {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		Ok(value.as_string()?.get()?.chars().next().unwrap())
	}
}

impl<'a> IntoNodeApi<'a> for &'a str {
	fn into_node_api(self, env: Env<'a>) -> Result<Value<'a>> {
		Ok(String::new(env, self)?.value())
	}
}

impl<'a> IntoNodeApi<'a> for std::string::String {
	fn into_node_api(self, env: Env<'a>) -> Result<Value<'a>> {
		Ok(String::new(env, self.as_str())?.value())
	}
}

impl<'a> FromNodeAPI<'a> for std::string::String {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_string()?.get()
	}
}

impl<'a, T> IntoNodeApi<'a> for Option<T>
where
	T: IntoNodeApi<'a>,
{
	fn into_node_api(self, env: Env<'a>) -> Result<Value<'a>> {
		match self {
			None => Ok(Null::new(env)?.value()),
			Some(value) => Ok(value.into_node_api(env)?),
		}
	}
}

impl<'a, T> FromNodeAPI<'a> for Option<T>
where
	T: FromNodeAPI<'a>,
{
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		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<T>
where
	T: IntoNodeApi<'a>,
{
	fn into_node_api(self, env: Env<'a>) -> Result<Value<'a>> {
		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<T>
where
	T: FromNodeAPI<'a>,
{
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		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<Value<'a>> {
		Ok(self)
	}
}

impl<'a> FromNodeAPI<'a> for Value<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		Ok(value)
	}
}

impl<'a> IntoNodeApi<'a> for Array<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Array<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_array()
	}
}

impl<'a> IntoNodeApi<'a> for ArrayBuffer<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for ArrayBuffer<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_arraybuffer()
	}
}

impl<'a> IntoNodeApi<'a> for BigInt<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for BigInt<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_bigint()
	}
}

impl<'a> IntoNodeApi<'a> for Boolean<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Boolean<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_boolean()
	}
}

impl<'a> IntoNodeApi<'a> for Buffer<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Buffer<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_buffer()
	}
}

impl<'a> IntoNodeApi<'a> for DataView<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a, 'b: 'a> FromNodeAPI<'a> for DataView<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_dataview()
	}
}

impl<'a> IntoNodeApi<'a> for Date<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Date<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_date()
	}
}

impl<'a, T: 'a> IntoNodeApi<'a> for External<'a, T> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a, T: 'a> FromNodeAPI<'a> for External<'a, T> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_external()
	}
}

impl<'a> IntoNodeApi<'a> for Function<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Function<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_function()
	}
}

impl<'a> IntoNodeApi<'a> for Null<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Null<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_null()
	}
}

impl<'a> IntoNodeApi<'a> for Number<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Number<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_number()
	}
}

impl<'a> IntoNodeApi<'a> for Object<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Object<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_object()
	}
}

impl<'a> IntoNodeApi<'a> for String<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for String<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		let value = value.as_string()?;
		Ok(value)
	}
}

impl<'a> IntoNodeApi<'a> for Symbol<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Symbol<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_symbol()
	}
}

impl<'a> IntoNodeApi<'a> for TypedArray<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for TypedArray<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_typedarray()
	}
}

impl<'a> IntoNodeApi<'a> for Undefined<'a> {
	fn into_node_api(self, _env: Env<'a>) -> Result<Value<'a>> {
		Ok(self.value())
	}
}

impl<'a> FromNodeAPI<'a> for Undefined<'a> {
	fn from_node_api(value: Value<'a>) -> Result<Self> {
		value.as_undefined()
	}
}