Skip to content

Commit 48b97ce

Browse files
authored
Merge pull request #4 from Rhea-OS/query
query
2 parents bb8fd30 + a94c5cb commit 48b97ce

File tree

4 files changed

+40
-67
lines changed

4 files changed

+40
-67
lines changed

expression-js/src/context.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,13 @@ pub(crate) fn value_to_js_object(value: Object) -> Option<JsValue> {
104104
JsValue::from(key_map)
105105
},
106106
Object::Nothing => JsValue::null(),
107-
Object::Function(_) => wasm_bindgen::throw_str("Cannot convert Rust closure to JS value"),
107+
Object::Function(function) => JsClosure::new(move |args| -> JsValue {
108+
wasm_bindgen::throw_str("Fuck you");
109+
function(vec![])
110+
.map(value_to_js_object)
111+
.unwrap_throw()
112+
.unwrap_throw()
113+
}).into(),
108114
})
109115
}
110116

@@ -171,6 +177,7 @@ impl Context {
171177
global::Inner::ManualError(ManualError::NoSuchOperator(op)) => format!("The operator '{}' was not recognised", op),
172178
global::Inner::ManualError(ManualError::NoSuchValue(value)) => format!("'{}' is not defined", value),
173179
global::Inner::ManualError(ManualError::OperationNotValidForType(op)) => format!("The operation '{}' was attempted on an invalid type", op),
180+
global::Inner::ManualError(ManualError::EmptyResultSet(query)) => format!("The query '{}' returned no results", query),
174181
err => format!("Miscellaneous Error: {:?}", err)
175182
});
176183

@@ -185,4 +192,17 @@ impl Context {
185192
wasm_bindgen::throw_str("Unable to convert result back into JS");
186193
}
187194
}
195+
}
196+
197+
#[wasm_bindgen]
198+
struct JsClosure {
199+
closure: Closure<dyn Fn()>,
200+
}
201+
202+
impl JsClosure {
203+
pub fn new(handler: impl Fn(JsValue) -> JsValue + 'static) -> Self {
204+
Self {
205+
closure: Closure::new(|| {})
206+
}
207+
}
188208
}

expression-js/src/datasource.rs

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
use crate::{
2+
context::js_value_to_object,
3+
context::value_to_js_object
4+
};
5+
use expression::Object;
16
use std::rc::Rc;
27
use wasm_bindgen::{
8+
prelude::*,
39
JsValue,
410
UnwrapThrowExt,
5-
prelude::*
11+
convert::FromWasmAbi,
12+
convert::IntoWasmAbi,
13+
__rt::WasmRefCell
614
};
7-
use wasm_bindgen::__rt::WasmRefCell;
8-
use wasm_bindgen::convert::{FromWasmAbi, IntoWasmAbi};
9-
use expression::{Column, ManualError, Object};
10-
use crate::context::{js_value_to_object, value_to_js_object};
1115

1216
#[wasm_bindgen(js_name=Address)]
1317
pub struct Address(expression::Address);
@@ -50,7 +54,7 @@ const DATA_SOURCE_CONFIG: &'static str = r#"
5054

5155
#[wasm_bindgen(js_name=DataSource)]
5256
pub struct DataSource {
53-
query: js_sys::Function,
57+
query_handler: js_sys::Function,
5458

5559
pub(crate) cx: Rc<WasmRefCell<Object>>
5660
}
@@ -59,41 +63,21 @@ pub struct DataSource {
5963
impl DataSource {
6064
#[wasm_bindgen(constructor)]
6165
pub fn new(config: JsValue) -> crate::DataSource {
62-
let query = js_sys::Function::from(js_sys::Reflect::get(&config, &JsValue::from_str("query"))
63-
.unwrap_throw());
64-
6566
crate::DataSource {
66-
query,
67+
query_handler: js_sys::Function::from(js_sys::Reflect::get(&config, &JsValue::from_str("query"))
68+
.unwrap_throw()),
6769

6870
cx: Rc::new(WasmRefCell::new(Object::Nothing))
6971
}
7072
}
7173
}
7274

73-
#[wasm_bindgen]
74-
pub struct RowWrapper(js_sys::Object);
75-
76-
impl expression::Row for crate::RowWrapper {
77-
#[allow(refining_impl_trait)]
78-
fn fields(&self) -> impl Iterator<Item=String> + Clone {
79-
js_sys::Object::keys(&self.0).into_iter()
80-
.filter(|i| i.is_string())
81-
.flat_map(|v| v.as_string())
82-
}
83-
84-
fn get(&self, field: &str) -> Option<expression::Object> {
85-
js_sys::Reflect::get(&self.0, &JsValue::from_str(field)).ok()
86-
.and_then(|i| match i {
87-
i if i.is_string() => Some(expression::Object::String(i.as_string()?)),
88-
i if i.as_f64().is_some() => Some(expression::Object::Number(i.as_f64()?)),
89-
_ => Some(expression::Object::Nothing)
90-
})
91-
}
92-
}
93-
9475
impl expression::DataSource for DataSource {
9576
fn query(&self, query: impl AsRef<str>) -> Option<Object> {
96-
match self.query.call1(&JsValue::null(), &JsValue::from_str(query.as_ref())) {
77+
let cx = value_to_js_object(self.cx.borrow().clone())
78+
.unwrap_or(JsValue::null());
79+
80+
match self.query_handler.call2(&JsValue::null(), &cx, &JsValue::from_str(query.as_ref())) {
9781
Ok(value) => Some(js_value_to_object(value)?),
9882
Err(_) => None
9983
}

src/eval/context.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -218,36 +218,6 @@ where
218218
self.operators.insert(operator.symbol.clone(), operator);
219219
}
220220

221-
// pub fn resolve_name(&self, name: String) -> Result<Object> {
222-
// let mut chain = name.split('.');
223-
//
224-
// 'outer: {
225-
// if let Some(obj) = chain.next().and_then(|key| self.globals.get(key)) {
226-
// let mut object = obj;
227-
//
228-
// while let Some(next) = chain.next() {
229-
// match object {
230-
// Object::AssociativeArray(arr) => if let Some(obj) = arr.get(next) {
231-
// object = obj;
232-
// } else {
233-
// break 'outer;
234-
// },
235-
// Object::List(list) => if let Ok(Some(obj)) = next.parse::<usize>().map(|a| list.get(a)) {
236-
// object = obj
237-
// } else {
238-
// break 'outer;
239-
// },
240-
// _ => break 'outer,
241-
// }
242-
// }
243-
//
244-
// return Ok(object.clone());
245-
// }
246-
// }
247-
//
248-
// Err(ManualError::NoSuchValue(name.clone()).into())
249-
// }
250-
251221
pub fn call_object(&self, object: Object, arguments: &[Object]) -> Result<Object> {
252222
if let Object::Function(obj) = object {
253223
obj(arguments.iter().cloned().collect())
@@ -279,8 +249,8 @@ where
279249
.cloned()
280250
.ok_or(ManualError::NoSuchValue(name.clone()).into()),
281251

282-
Literal::Address(address) => self.query(&address.query)
283-
.ok_or(ManualError::EmptyResultSet(address.query).into())
252+
Literal::Address(address) => Ok(self.query(&address.query)
253+
.unwrap_or(Object::Nothing)),
284254
}
285255

286256
Value::Call(Call { name, arguments }) => self.call_object(self.evaluate_value(*name)?, &arguments

src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ pub mod error;
1010
pub mod parse;
1111
pub mod eval;
1212
mod vec;
13-
// mod hashmap;
1413

1514
pub use crate::error::*;
1615
pub use crate::eval::*;
@@ -19,7 +18,7 @@ pub use crate::parse::literal::Address;
1918
pub use crate::parse::literal::Column;
2019

2120
/// # Data Source
22-
/// A datasource may be thought of as a self-contained table.
21+
/// A datasource which responds to queries.
2322
/// It may produce its values either by reading them from a data source or computing them directly.
2423
///
2524
/// ## Examples of where data sources are useful

0 commit comments

Comments
 (0)