Skip to content

Instantly share code, notes, and snippets.

@qryxip
Last active May 1, 2017 04:55
Show Gist options
  • Save qryxip/f723e163b1b68c323e7cf19399b35775 to your computer and use it in GitHub Desktop.
Save qryxip/f723e163b1b68c323e7cf19399b35775 to your computer and use it in GitHub Desktop.
https://github.com/neon-bindings/neon のドキュメントのサンプルコードが古いので
#[macro_use]
extern crate neon;
use neon::js::{JsInteger, JsString, JsUndefined, Object, Value};
use neon::js::class::Class;
use neon::vm::{FunctionCall, JsResult, Lock, This, Throw};
use std::ops::FnOnce;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
register_module!(m, {
let timer_constructor = JsTimer::class(m.scope)?.constructor(m.scope)?;
(*m.exports).set("Timer", timer_constructor)?;
Ok(())
});
declare_types! {
pub class JsTimer for Timer {
init(_) {
Ok(Timer::new())
}
method start(mut call) {
call.grab_this(|this| this.start());
Ok(JsUndefined::new().upcast())
}
method increase(mut call) {
let n = call.check_argument::<JsInteger>(0)?.value() as i32;
call.grab_this(|this| this.increase(n));
Ok(JsUndefined::new().upcast())
}
method get(mut call) {
let time = call.grab_this(|this| this.get());
Ok(JsInteger::new(call.scope, time).upcast())
}
method asString(mut call) {
let result = call.grab_this(|this| this.asString());
Ok(JsString::new(call.scope, &result).ok_or(Throw)?.upcast())
}
}
}
pub struct Timer(Arc<Mutex<i32>>);
#[allow(non_snake_case)]
impl Timer {
fn new() -> Timer {
Timer(Arc::new(Mutex::new(0)))
}
fn start(&self) {
let time = self.0.clone();
let go = move || loop {
thread::sleep(Duration::from_millis(1000));
*time.lock().unwrap() += 1;
};
thread::spawn(go);
}
fn increase(&self, n: i32) {
*self.0.lock().unwrap() += n;
}
fn get(&self) -> i32 {
*self.0.lock().unwrap()
}
fn asString(&self) -> String {
let time = self.get();
if time > 1 {
format!("{} seconds passed.", time)
} else {
format!("{} second passed.", time)
}
}
}
trait CheckArgument<'a> {
fn check_argument<V: Value>(&mut self, i: i32) -> JsResult<'a, V>;
}
impl<'a, T: This> CheckArgument<'a> for FunctionCall<'a, T> {
fn check_argument<V: Value>(&mut self, i: i32) -> JsResult<'a, V> {
self.arguments.require(self.scope, i)?.check::<V>()
}
}
trait GrabThis<'a, T: Class> {
fn grab_this<F, R>(&mut self, f: F) -> R
where F: FnOnce(&mut <T as Class>::Internals) -> R + Send;
}
impl<'a, T: Class> GrabThis<'a, T> for FunctionCall<'a, T> {
fn grab_this<F, R>(&mut self, f: F) -> R
where F: FnOnce(&mut <T as Class>::Internals) -> R + Send
{
self.arguments.this(self.scope).grab(f)
}
}
const native = require("./path/to/module");
let timer = new native.Timer();
timer.start();
console.log(timer.get()); // 0
(new Promise(resolve => setTimeout(resolve, 3500))).then(() => {
console.log(timer.get()); // 3
timer.increase(5);
console.log(timer.asString()); // "8 seconds passed."
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment