1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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};
#[repr(C)]
#[derive(Debug, Copy, Clone)]
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(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 {
fmt.write_str(self.0.as_str())
}
}
impl Error for DateError {}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum DateErrorKind {
Overflow,
Underflow,
}
impl DateErrorKind {
fn as_str(&self) -> &'static str {
match *self {
DateErrorKind::Overflow => "Date overflow",
DateErrorKind::Underflow => "Date underflow",
}
}
}
impl<'a, T: Value> JsResultExt<'a, T> for Result<Handle<'a, T>, DateError> {
fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> {
self.or_else(|e| cx.throw_range_error(e.0.as_str()))
}
}
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)
};
let date = Handle::new_internal(JsDate(local));
Ok(date)
}
pub fn new_lossy<'a, C: Context<'a>, V: Into<f64>>(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 { }