Neon: How to Get an Array of Objects as an Argument?

Created on 10 Sep 2019  路  4Comments  路  Source: neon-bindings/neon

Context:

[build-dependencies]
neon-build = "0.3.1"

[dependencies]
neon = "0.3.1"

I have a Javascript collection that has the following structure:

[ 
  { 
    sortCode: '',
    completionStatus: 'Complete',
    packageSize: '1',
    unitOfMeasure: 'ML',
    strength: '156',
    codeType: 'NDC',
    genericCode: '523850',
    drugType: 'Brand',
    ndc: '50458-0563-01',
    drugName: 'INVEGA SUSTENNA 156 MG/ML S',
    quanityDispensed: '1',
    cost: '$1,707.15',
    fillDate: '5/1/2019',
    poGroupMaster: 'None',
    reOrderPoint: '',
    isPricedByPackage: 'Priced by unit' 
  },
  ... // more objects here
]

I'd like to pass this drugs collection and a property string as parameters into a Rust function. This function would return the object in the collection that has the minimum value for property, i.e. cost. In this case I'll also need to parse each cost property to a number so that it can be numerically compared.

So far, my Rust function looks like this

use neon::prelude::*;

pub fn has_min(mut cx: FunctionContext) -> JsResult<JsObject> {
    let js_array_handle: Handle<JsArray> = cx.argument(0)?; // this is the 'drugs' array from JS
    let min_key = cx.argument::<JsString>(0)?.value(); // This is the `property` string from JS

    let vec: Vec<Handle<JsValue>> = js_array_handle.to_vec(&mut cx)?;

    let vec_of_objects: Vec<JsObject> = vec
        .iter()
        .map(|js_value| {
            js_value
                .downcast::<JsObject>()
                // If downcast fails, default to using 0
                .unwrap_or(JsObject::new(&mut cx))
                // Get the value of the unwrapped value
                .value() // error here: no method named `value` found for type `neon::handle::Handle<'_, neon::types::JsObject>` in the current scope
        })
        .collect();

    // I want to be able to get the min_by_key like this, 
    // but cannot figure out how to do so.
    return vec_of_objects
        .iter()
        .min_by_key(|js_object| min_key);
}

but I cannot figure out how to convert Vec<Handle<JsValue>> to Vec<JsObject>. I've tried to derive a solution from the examples but I do not understand it enough to figure it out myself yet. Any help would be greatly appreciated, and thanks for this awesome library!

All 4 comments

Is there a specific reason that you would like a JsObject instead of a Handle<JsObject>? Handle is a smart pointer (similar to Box). It implements Deref and in many cases can be used exactly like the inner value. After your downcast, you should have a Handle<JsObject>.

You may also be interested in neon-serde which leverages serde to more easily convert complex javascript objects into native rust structs.

Hi, thanks for your quick response! There is no reason other than my ignorance of smart pointers at this time. I'm currently studying the Rust book but am only on chapter 7.

neon-serde looks to be exactly what I need. However, I'm confused on how I would iterate the vec: Vec<Handle<JsValue>> and transform it into a Vec<Drug>, where Drug is defined like

#[derive(Serialize, Debug, Deserialize)]
struct Drug {
    cost:String,
    ... // other props
}

i am interested in how to implement this too

let drugs: Vec<Drug> = neon_serde::from_value(&mut cx, js_drugs)?;
Was this page helpful?
0 / 5 - 0 ratings