use crate::errors::RuntimeError;
use crate::memory::object_map::{ObjectKind, Structure};
use crate::memory::vm_data::VMData;
use crate::runtime::vm_state::VMState;
use crate::CallBack;
use time::{format_description, OffsetDateTime};
pub const TIME_FUNCTIONS: [(&str, CallBack); 4] = [
("now", now),
("format_time_iso", format_time_iso),
("format_time", format_time),
("elapsed", elapsed),
];
pub fn now(state: VMState) -> Result<VMData, RuntimeError> {
let time = std::time::SystemTime::now();
let duration = time.duration_since(std::time::UNIX_EPOCH).unwrap();
let sec = duration.as_secs();
let nsec = duration.subsec_nanos();
let obj_idx = state.object_map.put(ObjectKind::Structure(Structure {
fields: vec![VMData::new_i64(sec as i64), VMData::new_i64(nsec as i64)],
}));
match obj_idx {
Ok(index) => Ok(VMData::new_object(index)),
Err(_) => Err(RuntimeError::OutOfMemory),
}
}
pub fn format_time_iso(state: VMState) -> Result<VMData, RuntimeError> {
let time_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
let raw_time_obj = state.object_map.get(time_ptr)?;
let time_obj = raw_time_obj.structure();
let sec = time_obj.fields[0].as_i64();
let nsec = time_obj.fields[1].as_i64();
let time =
OffsetDateTime::from_unix_timestamp(sec).unwrap() + time::Duration::nanoseconds(nsec);
let fmt =
format_description::parse("[year]-[month]-[day]T[hour]:[minute]:[second].[frac][offset]")
.unwrap();
let formatted = time.format(&fmt).unwrap();
let obj_idx = state.object_map.put(ObjectKind::String(formatted));
match obj_idx {
Ok(index) => Ok(VMData::new_string(index)),
Err(_) => Err(RuntimeError::OutOfMemory),
}
}
pub fn format_time(state: VMState) -> Result<VMData, RuntimeError> {
let format_ptr = state.stack.pop_with_rc(state.object_map)?.as_object(); let time_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
let fmt_str = &state.object_map.get(format_ptr)?.string().clone();
let raw_time_obj = state.object_map.get(time_ptr)?;
let time_obj = raw_time_obj.structure();
let sec = time_obj.fields[0].as_i64();
let nsec = time_obj.fields[1].as_i64();
let time =
OffsetDateTime::from_unix_timestamp(sec).unwrap() + time::Duration::nanoseconds(nsec);
let fmt = format_description::parse(fmt_str).unwrap();
let formatted = time.format(&fmt).unwrap();
let obj_idx = state.object_map.put(ObjectKind::String(formatted));
match obj_idx {
Ok(index) => Ok(VMData::new_string(index)),
Err(_) => Err(RuntimeError::OutOfMemory),
}
}
pub fn elapsed(state: VMState) -> Result<VMData, RuntimeError> {
let end_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
let start_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
let start_obj = &state.object_map.get(start_ptr)?.structure().clone();
let raw_time_obj = state.object_map.get(end_ptr)?;
let end_obj = raw_time_obj.structure();
let start_sec = start_obj.fields[0].as_i64();
let start_nsec = start_obj.fields[1].as_i64();
let end_sec = end_obj.fields[0].as_i64();
let end_nsec = end_obj.fields[1].as_i64();
let elapsed_sec = end_sec - start_sec;
let elapsed_nsec = end_nsec - start_nsec;
let obj_idx = state.object_map.put(ObjectKind::Structure(Structure {
fields: vec![VMData::new_i64(elapsed_sec), VMData::new_i64(elapsed_nsec)],
}));
match obj_idx {
Ok(index) => Ok(VMData::new_object(index)),
Err(_) => Err(RuntimeError::OutOfMemory),
}
}