use std::{ops::Deref, time::{Duration, SystemTime, UNIX_EPOCH}};
use crate::{lang::SError, Library, SDoc, SNum, SUnits, SVal};
#[derive(Default, Debug)]
pub struct TimeLibrary;
impl Library for TimeLibrary {
fn scope(&self) -> String {
"Time".to_string()
}
fn call(&self, pid: &str, doc: &mut SDoc, name: &str, parameters: &mut Vec<SVal>) -> Result<SVal, SError> {
match name {
"now" => {
let now = SystemTime::now();
let dur = now.duration_since(UNIX_EPOCH).unwrap();
Ok(SVal::Number(SNum::Units(dur.as_millis() as f64, SUnits::Milliseconds)))
},
"nowNano" => {
let now = SystemTime::now();
let dur = now.duration_since(UNIX_EPOCH).unwrap();
Ok(SVal::Number(SNum::Units(dur.as_nanos() as f64, SUnits::Nanoseconds)))
},
"diff" => {
if parameters.len() < 1 {
return Err(SError::time(pid, &doc, "diff", "expecting a number to diff with"));
}
match ¶meters[0] {
SVal::Number(num) => {
let prev = num.float_with_units(SUnits::Milliseconds);
let now = SystemTime::now();
let dur = now.duration_since(UNIX_EPOCH).unwrap();
return Ok(SVal::Number(SNum::Units((dur.as_millis() as f64) - prev, SUnits::Milliseconds)));
},
SVal::Boxed(val) => {
let val = val.lock().unwrap();
let val = val.deref();
match val {
SVal::Number(num) => {
let prev = num.float_with_units(SUnits::Milliseconds);
let now = SystemTime::now();
let dur = now.duration_since(UNIX_EPOCH).unwrap();
return Ok(SVal::Number(SNum::Units((dur.as_millis() as f64) - prev, SUnits::Milliseconds)));
},
_ => {}
}
},
_ => {}
}
Err(SError::time(pid, &doc, "diff", "expecting a number to diff with"))
},
"diffNano" => {
if parameters.len() < 1 {
return Err(SError::time(pid, &doc, "diffNano", "expecting a number to diff with"));
}
match ¶meters[0] {
SVal::Number(num) => {
let prev = num.float_with_units(SUnits::Nanoseconds);
let now = SystemTime::now();
let dur = now.duration_since(UNIX_EPOCH).unwrap();
return Ok(SVal::Number(SNum::Units((dur.as_nanos() as f64) - prev, SUnits::Nanoseconds)));
},
SVal::Boxed(val) => {
let val = val.lock().unwrap();
let val = val.deref();
match val {
SVal::Number(num) => {
let prev = num.float_with_units(SUnits::Nanoseconds);
let now = SystemTime::now();
let dur = now.duration_since(UNIX_EPOCH).unwrap();
return Ok(SVal::Number(SNum::Units((dur.as_nanos() as f64) - prev, SUnits::Nanoseconds)));
},
_ => {}
}
},
_ => {}
}
Err(SError::time(pid, &doc, "diffNano", "expecting a number to diff with"))
},
"sleep" => {
if parameters.len() < 1 {
return Err(SError::time(pid, &doc, "sleep", "expecting a number to use for sleep"));
}
match ¶meters[0] {
SVal::Number(num) => {
let mut dur = num.float_with_units(SUnits::Milliseconds);
if dur < 0. { dur *= -1.; }
let dur = Duration::from_millis(dur as u64);
std::thread::sleep(dur);
return Ok(SVal::Void);
},
SVal::Boxed(val) => {
let val = val.lock().unwrap();
let val = val.deref();
match val {
SVal::Number(num) => {
let mut dur = num.float_with_units(SUnits::Milliseconds);
if dur < 0. { dur *= -1.; }
let dur = Duration::from_millis(dur as u64);
std::thread::sleep(dur);
return Ok(SVal::Void);
},
_ => {}
}
},
_ => {}
}
Err(SError::time(pid, &doc, "sleep", "expecting a number to use for sleep"))
},
"sleepNano" => {
if parameters.len() < 1 {
return Err(SError::time(pid, &doc, "sleepNano", "expecting a number to use for sleep"));
}
match ¶meters[0] {
SVal::Number(num) => {
let mut dur = num.float_with_units(SUnits::Nanoseconds);
if dur < 0. { dur *= -1.; }
let dur = Duration::from_nanos(dur as u64);
std::thread::sleep(dur);
return Ok(SVal::Void);
},
SVal::Boxed(val) => {
let val = val.lock().unwrap();
let val = val.deref();
match val {
SVal::Number(num) => {
let mut dur = num.float_with_units(SUnits::Nanoseconds);
if dur < 0. { dur *= -1.; }
let dur = Duration::from_nanos(dur as u64);
std::thread::sleep(dur);
return Ok(SVal::Void);
},
_ => {}
}
},
_ => {}
}
Err(SError::time(pid, &doc, "sleepNano", "expecting a number to use for sleep"))
},
_ => {
Err(SError::time(pid, &doc, "NotFound", &format!("{} is not a function in the Time Library", name)))
}
}
}
}