Skip to content

Commit

Permalink
fix: refator date logic to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
amilajack committed Jan 9, 2021
1 parent 0426692 commit 7a5ae29
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 152 deletions.
23 changes: 18 additions & 5 deletions crates/neon-runtime/src/napi/bindings/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ mod napi1 {

fn get_value_double(env: Env, value: Value, result: *mut f64) -> Status;

fn create_date(env: Env, value: f64, result: *mut Value) -> Status;

fn get_date_value(env: Env, value: Value, result: *mut f64) -> Status;

fn create_array_with_length(env: Env, length: usize, result: *mut Value) -> Status;

fn get_array_length(env: Env, value: Value, result: *mut u32)-> Status;
Expand Down Expand Up @@ -57,7 +53,6 @@ mod napi1 {
fn is_buffer(env: Env, value: Value, result: *mut bool) -> Status;
fn is_error(env: Env, value: Value, result: *mut bool) -> Status;
fn is_array(env: Env, value: Value, result: *mut bool) -> Status;
fn is_date(env: Env, value: Value, result: *mut bool) -> Status;

fn get_value_string_utf8(
env: Env,
Expand Down Expand Up @@ -256,6 +251,19 @@ mod napi4 {
});
}

#[cfg(feature = "napi-5")]
mod napi5 {
use super::super::types::*;

generate!(extern "C" {
fn create_date(env: Env, value: f64, result: *mut Value) -> Status;

fn get_date_value(env: Env, value: Value, result: *mut f64) -> Status;

fn is_date(env: Env, value: Value, result: *mut bool) -> Status;
});
}

#[cfg(feature = "napi-6")]
mod napi6 {
use super::super::types::*;
Expand All @@ -275,6 +283,8 @@ mod napi6 {
pub(crate) use napi1::*;
#[cfg(feature = "napi-4")]
pub(crate) use napi4::*;
#[cfg(feature = "napi-5")]
pub(crate) use napi5::*;
#[cfg(feature = "napi-6")]
pub(crate) use napi6::*;

Expand Down Expand Up @@ -308,6 +318,9 @@ pub(crate) unsafe fn load(env: Env) -> Result<(), libloading::Error> {
#[cfg(feature = "napi-4")]
napi4::load(&host, version, 4)?;

#[cfg(feature = "napi-5")]
napi5::load(&host, version, 5)?;

#[cfg(feature = "napi-6")]
napi6::load(&host, version, 6)?;

Expand Down
1 change: 1 addition & 0 deletions crates/neon-runtime/src/napi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod scope;
pub mod string;
pub mod tag;
pub mod reference;
#[cfg(feature = "napi-5")]
pub mod date;
#[cfg(feature = "napi-4")]
pub mod tsfn;
Expand Down
5 changes: 3 additions & 2 deletions src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use handle::{Managed, Handle};
use event::EventQueue;
use types::{JsValue, Value, JsObject, JsArray, JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined};
#[cfg(feature = "napi-5")]
use types::JsDate;
use types::date::{JsDate, DateError};
#[cfg(feature = "napi-1")]
use types::boxed::{Finalize, JsBox};
use types::binary::{JsArrayBuffer, JsBuffer};
Expand All @@ -29,6 +29,7 @@ use object::class::Class;
use result::{NeonResult, JsResult, Throw};
#[cfg(feature = "napi-1")]
use smallvec::SmallVec;

use self::internal::{ContextInternal, Scope, ScopeMetadata};

#[repr(C)]
Expand Down Expand Up @@ -316,7 +317,7 @@ pub trait Context<'a>: ContextInternal<'a> {
}

#[cfg(feature = "napi-5")]
fn date(&mut self, value: impl Into<f64>) -> Handle<'a, JsDate> {
fn date(&mut self, value: impl Into<f64> + PartialOrd) -> Result<Handle<'a, JsDate>, DateError> {
JsDate::new(self, value)
}

Expand Down
119 changes: 119 additions & 0 deletions src/types/date.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use std;
use std::fmt;
use std::fmt::Debug;
use std::error::Error;
use neon_runtime;
use neon_runtime::raw;
use context::{Context};
use context::internal::Env;
use result::{JsResult, JsResultExt};
use object::{Object};
use handle::{Handle, Managed};
use super::{Value, ValueInternal};

/// A JavaScript Date object.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct JsDate(raw::Local);

impl Value for JsDate { }

impl Managed for JsDate {
fn to_raw(self) -> raw::Local { self.0 }

fn from_raw(_: Env, h: raw::Local) -> Self { JsDate(h) }
}

#[derive(PartialEq, PartialOrd, Clone, Debug)]
pub struct DateError(DateErrorKind);

impl DateError {
pub fn kind(&self) -> DateErrorKind {
self.0
}
}

impl fmt::Display for DateError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.0.as_str())
}
}

impl Error for DateError {}

#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
pub enum DateErrorKind {
Overflow,
Underflow,
}

impl DateErrorKind {
fn as_str(&self) -> &'static str {
match *self {
DateErrorKind::Overflow => "Uncaught RangeError: Date overflow",
DateErrorKind::Underflow => "Uncaught RangeError: Date underflow",
}
}
}

impl<'a> JsResultExt<'a, JsDate> for Result<Handle<'a, JsDate>, DateError> {
/// Creates a `Error` on error
fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, JsDate> {
match self {
Ok(v) => Ok(v),
Err(e) => cx.throw_range_error(&e.to_string())
}
}
}

impl JsDate {
pub const MIN_VALUE: f64 = -8.64e15;
pub const MAX_VALUE: f64 = 8.64e15;

pub fn new<'a, C: Context<'a>, T: Into<f64>>(cx: &mut C, value: T) -> Result<Handle<'a, JsDate>, DateError> {
let env = cx.env().to_raw();
let time = value.into();

if time > JsDate::MAX_VALUE {
return Err(DateError(DateErrorKind::Overflow))
} else if time < JsDate::MIN_VALUE {
return Err(DateError(DateErrorKind::Underflow))
}

let local = unsafe {
neon_runtime::date::new_date(env, time.clone())
};
let date = Handle::new_internal(JsDate(local));
Ok(date)
}

pub fn new_lossy<'a, C: Context<'a>, V: Into<f64> + std::cmp::PartialOrd>(cx: &mut C, value: V) -> Handle<'a, JsDate> {
let env = cx.env().to_raw();
let local = unsafe {
neon_runtime::date::new_date(env, value.into())
};
Handle::new_internal(JsDate(local))
}

pub fn value<'a, C: Context<'a>>(self, cx: &mut C) -> f64 {
let env = cx.env().to_raw();
unsafe {
neon_runtime::date::value(env, self.to_raw())
}
}

pub fn is_valid<'a, C: Context<'a>>(self, cx: &mut C) -> bool {
let value = self.value(cx);
value <= JsDate::MAX_VALUE && value >= JsDate::MIN_VALUE
}
}

impl ValueInternal for JsDate {
fn name() -> String { "object".to_string() }

fn is_typeof<Other: Value>(env: Env, other: Other) -> bool {
unsafe { neon_runtime::tag::is_date(env.to_raw(), other.to_raw()) }
}
}

impl Object for JsDate { }
127 changes: 4 additions & 123 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub(crate) mod binary;
#[cfg(feature = "napi-1")]
pub(crate) mod boxed;
pub(crate) mod error;
#[cfg(feature = "napi-5")]
pub(crate) mod date;

pub(crate) mod internal;
pub(crate) mod utf8;
Expand All @@ -13,7 +15,6 @@ use std::fmt;
use std::os::raw::c_void;
use std::marker::PhantomData;
use std::fmt::Debug;
use std::error::Error;
use neon_runtime;
use neon_runtime::raw;
use context::{Context, FunctionContext};
Expand All @@ -31,6 +32,8 @@ pub use self::binary::{JsBuffer, JsArrayBuffer, BinaryData, BinaryViewType};
#[cfg(feature = "napi-1")]
pub use self::boxed::JsBox;
pub use self::error::JsError;
#[cfg(feature = "napi-5")]
pub use self::date::{JsDate, DateError, DateErrorKind};

pub(crate) fn build<'a, T: Managed, F: FnOnce(&mut raw::Local) -> bool>(env: Env, init: F) -> JsResult<'a, T> {
unsafe {
Expand Down Expand Up @@ -426,128 +429,6 @@ impl ValueInternal for JsNumber {
}
}

/// A JavaScript Date object.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
#[cfg(feature = "napi-5")]
pub struct JsDate(raw::Local);

#[cfg(feature = "napi-5")]
impl Value for JsDate { }

#[cfg(feature = "napi-5")]
impl Managed for JsDate {
fn to_raw(self) -> raw::Local { self.0 }

fn from_raw(_: Env, h: raw::Local) -> Self { JsDate(h) }
}

#[cfg(feature = "napi-5")]
#[derive(PartialEq, PartialOrd, Clone, Debug)]
pub struct DateError(f64, DateErrorKind);

#[cfg(feature = "napi-5")]
impl DateError {
pub fn kind(&self) -> DateErrorKind {
self.1
}
}

#[cfg(feature = "napi-5")]
impl fmt::Display for DateError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.1.as_str())
}
}

#[cfg(feature = "napi-5")]
impl Error for DateError {}

#[cfg(feature = "napi-5")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
pub enum DateErrorKind {
Overflow,
Underflow,
}

#[cfg(feature = "napi-5")]
impl DateErrorKind {
pub fn as_str(&self) -> &'static str {
match *self {
DateErrorKind::Overflow => "date overflow",
DateErrorKind::Underflow => "date underflow",
}
}
}

#[cfg(feature = "napi-5")]
pub type DateResult<'a> = Result<Handle<'a, JsDate>, DateError>;

#[cfg(feature = "napi-5")]
impl<'a> JsResultExt<'a, JsDate> for DateResult<'a> {
/// Creates a `Error` on error
fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, JsDate> {
match self {
Ok(v) => Ok(v),
Err(e) => cx.throw_error(&e.to_string())
}
}
}

#[cfg(feature = "napi-5")]
impl JsDate {
pub const MIN_VALUE: f64 = -8.64e15;
pub const MAX_VALUE: f64 = 8.64e15;

pub fn new<'a, C: Context<'a>, T: Into<f64>>(cx: &mut C, time: T) -> Handle<'a, JsDate> {
let env = cx.env().to_raw();
let local = unsafe {
neon_runtime::date::new_date(env, time.into())
};
Handle::new_internal(JsDate(local))
}

pub fn new_lossy<'a, C: Context<'a>, V: Into<f64> + std::cmp::PartialOrd>(cx: &mut C, value: V) -> DateResult<'a> {
let env = cx.env().to_raw();
let time = value.into();
let local = unsafe {
neon_runtime::date::new_date(env, time.clone())
};
let date = Handle::new_internal(JsDate(local));
if date.is_valid(cx) { return Ok(date); }

if time > JsDate::MAX_VALUE {
Err(DateError(time, DateErrorKind::Overflow))
} else {
Err(DateError(time, DateErrorKind::Underflow))
}
}

pub fn value<'a, C: Context<'a>>(self, cx: &mut C) -> f64 {
let env = cx.env().to_raw();
unsafe {
neon_runtime::date::value(env, self.to_raw())
}
}

pub fn is_valid<'a, C: Context<'a>>(self, cx: &mut C) -> bool {
let value = self.value(cx);
return value <= JsDate::MAX_VALUE && value >= JsDate::MIN_VALUE;
}
}

#[cfg(feature = "napi-5")]
impl ValueInternal for JsDate {
fn name() -> String { "object".to_string() }

fn is_typeof<Other: Value>(env: Env, other: Other) -> bool {
unsafe { neon_runtime::tag::is_date(env.to_raw(), other.to_raw()) }
}
}

#[cfg(feature = "napi-5")]
impl Object for JsDate { }

/// A JavaScript object.
#[repr(C)]
#[derive(Clone, Copy)]
Expand Down
Loading

0 comments on commit 7a5ae29

Please sign in to comment.