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
use napi::{ CallContext, Env, Error, JsBoolean, JsNumber, JsObject, JsString, JsUndefined, Property, Result, }; use napi_derive::{js_function, module_exports}; use once_cell::sync::OnceCell; use rillrate::RillRate; use rillrate::{Counter, Gauge, Logger}; use std::convert::TryInto; static RILLRATE: OnceCell<RillRate> = OnceCell::new(); fn js_err(reason: impl ToString) -> Error { Error::from_reason(reason.to_string()) } #[js_function] fn install(ctx: CallContext) -> Result<JsUndefined> { let rillrate = RillRate::from_env("js").map_err(js_err)?; RILLRATE .set(rillrate) .map_err(|_| js_err("can't install RillRate shared object"))?; ctx.env.get_undefined() } macro_rules! js_decl { (@new $cls:ident, $name:ident) => { #[js_function(1)] fn $name(ctx: CallContext) -> Result<JsUndefined> { let arg0 = ctx.get::<JsString>(0)?.into_utf8()?.into_owned()?; let mut this: JsObject = ctx.this_unchecked(); let instance = $cls::create(&arg0).map_err(js_err)?; ctx.env.wrap(&mut this, instance)?; ctx.env.get_undefined() } }; (@bool $cls:ident, $meth:ident, $name:ident) => { #[js_function(1)] fn $name(ctx: CallContext) -> Result<JsBoolean> { let this: JsObject = ctx.this_unchecked(); let provider: &mut $cls = ctx.env.unwrap(&this)?; ctx.env.get_boolean(provider.$meth()) } }; (@f64 $cls:ident, $meth:ident, $name:ident) => { #[js_function(1)] fn $name(ctx: CallContext) -> Result<JsUndefined> { let arg0: f64 = ctx.get::<JsNumber>(0)?.try_into()?; let this: JsObject = ctx.this_unchecked(); let provider: &mut $cls = ctx.env.unwrap(&this)?; provider.$meth(arg0); ctx.env.get_undefined() } }; (@str $cls:ident, $meth:ident, $name:ident) => { #[js_function(1)] fn $name(ctx: CallContext) -> Result<JsUndefined> { let arg0 = ctx.get::<JsString>(0)?.into_utf8()?.into_owned()?; let this: JsObject = ctx.this_unchecked(); let provider: &mut $cls = ctx.env.unwrap(&this)?; provider.$meth(arg0); ctx.env.get_undefined() } }; } js_decl!(@new Gauge, gauge_constructor); js_decl!(@bool Gauge, is_active, gauge_is_active); js_decl!(@f64 Gauge, inc, gauge_inc); js_decl!(@f64 Gauge, dec, gauge_dec); js_decl!(@f64 Gauge, set, gauge_set); js_decl!(@new Counter, counter_constructor); js_decl!(@bool Counter, is_active, counter_is_active); js_decl!(@f64 Counter, inc, counter_inc); js_decl!(@new Logger, logger_constructor); js_decl!(@bool Logger, is_active, logger_is_active); js_decl!(@str Logger, log, logger_log); #[module_exports] fn init(mut exports: JsObject, env: Env) -> Result<()> { exports.create_named_method("install", install)?; let gauge_props = [ Property::new(&env, "isActive")?.with_method(gauge_is_active), Property::new(&env, "inc")?.with_method(gauge_inc), Property::new(&env, "dec")?.with_method(gauge_dec), Property::new(&env, "set")?.with_method(gauge_set), ]; let gauge_class = env.define_class("Gauge", gauge_constructor, &gauge_props)?; exports.set_named_property("Gauge", gauge_class)?; let counter = [ Property::new(&env, "isActive")?.with_method(counter_is_active), Property::new(&env, "inc")?.with_method(counter_inc), ]; let counter_class = env.define_class("Counter", counter_constructor, &counter)?; exports.set_named_property("Counter", counter_class)?; let logger = [ Property::new(&env, "isActive")?.with_method(logger_is_active), Property::new(&env, "log")?.with_method(logger_log), ]; let logger_class = env.define_class("Logger", logger_constructor, &logger)?; exports.set_named_property("Logger", logger_class)?; Ok(()) }