Skip to content

Instantly share code, notes, and snippets.

@jonathanstrong
Created March 4, 2022 03:04
Show Gist options
  • Save jonathanstrong/9431e5ca238f6ad544d8051744e595ea to your computer and use it in GitHub Desktop.
Save jonathanstrong/9431e5ca238f6ad544d8051744e595ea to your computer and use it in GitHub Desktop.
rhai panic isolated example
use std::sync::Arc;
use chrono::prelude::*;
use chrono_tz::US::Eastern;
use rhai::{Engine, EvalAltResult, Scope, FnPtr, NativeCallContext};
#[derive(Clone)]
pub struct Ts {
time: Vec<u64>,
data: Vec<f64>,
}
#[derive(Clone)]
pub struct TsWrapper {
ts: Arc<Ts>,
}
impl Ts {
pub fn with_time_range(&self, start: u64, end: u64) -> Self {
let i = self.time.binary_search(&start).unwrap_or_else(|x| x);
let j = (&self.time[i..]).binary_search(&end).unwrap_or_else(|x| x) + i;
let time = self.time[i..j].to_vec();
let data = self.data[i..j].to_vec();
Self { time, data }
}
pub fn len(&self) -> usize { self.time.len() }
}
impl TsWrapper {
pub fn range(&mut self, start: i64, end: i64) -> Self {
let out = self.ts.with_time_range(start as u64, end as u64);
TsWrapper { ts: Arc::new(out) }
}
pub fn len(&mut self) -> i64 {
self.ts.len() as i64
}
}
pub fn ymd(y: i64, m: i64, d: i64) -> i64 {
Eastern.ymd(y as i32, m as u32, d as u32)
.and_hms(0, 0, 0)
.timestamp_nanos()
}
fn main() -> Result<(), Box<EvalAltResult>> {
let one_hour: u64 = 1_000_000_000 * 60 * 60;
let one_day: u64 = 1_000_000_000 * 60 * 60 * 24;
let now = 1646361679508932724;
let t0 = (now - now % one_hour) - one_day*180;
let tlast = now - now%one_hour + one_hour;
let time: Vec<u64> = (t0..tlast)
.step_by(one_hour as usize)
.collect();
assert_eq!(time[1] - time[0], one_hour);
let data: Vec<f64> = (0..time.len())
.map(|i| i as f64 / 42.0)
.collect();
assert_eq!(time.len(), data.len());
// sanity check: performing `range` works ok here
assert!(ymd(2021, 12, 25) > time[0] as i64);
assert!(ymd(2022, 1, 1) < time[time.len()-1] as i64);
let ts = Ts { time, data };
let mut tw = TsWrapper { ts: Arc::new(ts) };
let tw2 = tw.range(ymd(2021,12,25),ymd(2022,1,1));
assert!(tw2.ts.time.len() < tw.ts.len());
let mut engine = Engine::new();
engine
.register_fn("ymd", ymd)
.register_type_with_name::<TsWrapper>("TsWrapper")
.register_fn("range", TsWrapper::range)
.register_fn("len", TsWrapper::len)
;
let mut scope = Scope::new();
scope.push_constant("tw", tw.clone());
let script = r#"
let xmas = ymd(2021, 12, 25);
print(`xmas (us/eastern) = ${xmas}`);
print(`tw.len() = ${tw.len()}`);
let tw3 = tw.range(0, 9223372036854775807);
let tw4 = tw.range(ymd(2021, 12, 25), ymd(2022, 1, 1));
print(`tw4.len() = ${tw4.len()}`);
tw4
"#;
engine.set_optimization_level(rhai::OptimizationLevel::Full);
let ast = engine.compile(script)?;
let mut tw4 = engine.eval_ast_with_scope::<TsWrapper>(&mut scope, &ast)?;
dbg!(tw4.len());
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment