neon
neon copied to clipboard
Question: Why are the conversions like they are?
I do not intend criticize the framework or the work that the developers have done, I just want to understand the reasoning behind the design of it. Also, I am very new to the framework and haven't built much aside from a few tests and I am not as acquainted with rust as I am with javascript. With that aside, here is my question: why is there a need to explicitly convert from javascript values to rust values? As far as I see it, it just adds bloat to your code. This is the example on how to pass an array to javascript:
fn convert_vec_to_array(mut cx: FunctionContext) -> JsResult<JsArray> {
let vec: Vec<String> = Vec::with_capacity(100);
// Create the JS array
let js_array = JsArray::new(&mut cx, vec.len() as u32);
// Iterate over the rust Vec and map each value in the Vec to the JS array
for (i, obj) in vec.iter().enumerate() {
let js_string = cx.string(obj);
js_array.set(&mut cx, i as u32, js_string).unwrap();
}
Ok(js_array)
}
What is preventing me from just returning a vector and having a match statement in the neon code someplace that converts the vector into a JsArray? And why isn't there a function that can convert a Vec to a JsArray? If it encounters a second Vec it could just recursively convert until it hits a primitive value, which it will eventually do. Same for structs or objects. There could very well be a good reason why some or all of these things are not possible, and I do not intend to criticize the current API. I just want to know why that is.
If conversion was to take place behind the scenes the same function could look like this:
fn convert_vec_to_array(mut cx: FunctionContext) -> std::io::Result<Vec<String>> {
let vec:Vec<String> = Vec::with_capacity(100);
Ok(vec)
}
then under the hood it would understand that Result should be a JsResult, Vec should be a JsArray and so on...
This could possibly extend to arguments as well, but that could have various issues with object types and such.
That kind of automated conversion is not trivial in a compiled language like Rust. For example, AFAIK it is ~impossible~ quite hard to write an .export_function method that can accept those signatures.
So, the current API is lower level. An option that we've been talking about is using a procedural macro to generate the conversion code at compile time, so that you could write the code from your second example, but that is still a ways off.
This is a feature we really want and some thoughts are starting to be put together for it. https://github.com/neon-bindings/rfcs/pull/43
We were blocked by GAT, but that will be landing soon and hopefully TryFromJs and TryIntoJs traits can be implemented.