Search code examples
rustborrow-checkerrust-polarspolars

Polars Rust Napi borrower checker


When creating a Polars Rust Napi function, I am running into a borrower checker error: returns a value referencing data owned by the current function Any help would be appreciated. Thx

#[napi(catch_unwind)]
pub fn from_rows(
    rows: Array,
    schema: Option<Wrap<Schema>>,
    infer_schema_length: Option<u32>,
    env: Env,
) -> napi::Result<JsDataFrame> {
    let schema = match schema {
        Some(s) => s.0,
        None => {
            let infer_schema_length = infer_schema_length.unwrap_or(100) as usize;
            let pairs = obj_to_pairs(&rows, infer_schema_length);
            infer_schema(pairs, infer_schema_length)
        }
    };
    let len = rows.len();
    let it: Vec<Row> = (0..len)
        .into_iter()
        .map(|idx| {
            let obj = rows
                .get::<Object>(idx as u32)
                .unwrap_or(None)
                .unwrap_or_else(|| env.create_object().unwrap());
            Row(schema
                .iter_fields()
                .map(|fld| {
                    let dtype = fld.dtype();
                    let key = fld.name();
                    if let Ok(unknown) = obj.get(key) {
                        let av = match unknown {
                            Some(unknown) => unsafe {
                                coerce_js_anyvalue(unknown, dtype).unwrap_or(AnyValue::Null)
                            },
                            None => AnyValue::Null,
                        };
                        // error is happening here
                        av // error: returns a value referencing data owned by the current function
                    } else {
                        AnyValue::Null
                    }
                })
                .collect())
        })
        .collect();
    let df = DataFrame::from_rows_and_schema(&it, &schema).map_err(JsPolarsErr::from)?;
    Ok(df.into())
}

Solution

  • #[napi(catch_unwind)]
    pub fn from_rows(
        rows: Array,
        schema: Option<Wrap<Schema>>,
        infer_schema_length: Option<u32>,
        env: Env,
    ) -> napi::Result<JsDataFrame> {
        let schema = match schema {
            Some(s) => s.0,
            None => {
                let infer_schema_length = infer_schema_length.unwrap_or(100) as usize;
                let pairs = obj_to_pairs(&rows, infer_schema_length);
                infer_schema(pairs, infer_schema_length)
            }
        };
        let len = rows.len();
        let it: Vec<Row> = (0..len)
            .into_iter()
            .map(|idx| {
                let obj = rows
                    .get::<Object>(idx as u32)
                    .unwrap_or(None)
                    .unwrap_or_else(|| env.create_object().unwrap());
    
                Row(schema
                    .iter_fields().map(|fld| {
                        let dtype: &DataType = unsafe { std::mem::transmute( fld.dtype() ) };
                        let key: &PlSmallStr = fld.name();
                        if let Ok(unknown) = obj.get::<&polars::prelude::PlSmallStr, JsUnknown>(key) {
                            match unknown {
                                Some(unknown) => unsafe {
                                    coerce_js_anyvalue(unknown, dtype).unwrap_or(AnyValue::Null)
                                },
                                _ => AnyValue::Null,
                            }
                        } else {
                            AnyValue::Null
                        }
                    }).collect()
                )
            })
            .collect();
        let df = DataFrame::from_rows_and_schema(&it, &schema).map_err(JsPolarsErr::from)?;
        Ok(df.into())
    }