Neon bindings example with RefCell not working - rust

I'm trying to figure out how to use native Rust modules in NodeJS using the Neon crate. To get started I was following an example using RefCell to make it possible to call mut functions on an object through JavaScript.
However, when I copy the example code, it doesn't compile. It says Cannot borrow immutable local variable 'person' as mutable & no method named 'set_name' found for mutable reference '&mut neon::handle::Handle<'_, neon::prelude::JsBox<std::cell::RefCell<Person>>>' in the current scope (positions given in comments in the code below)
I really need this kind of functionality in my app, because it needs some engine running in the background, controlled via JS. Any hints are appreciated.
It's about the following code (source):
type BoxedPerson = JsBox<RefCell<Person>>;
struct Person {
name: String,
}
impl Finalize for Person {}
impl Person {
pub fn new(name: String) -> Self {
Person { name }
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn greet(&self) -> String {
format!("Hello, {}!", self.name)
}
}
fn person_new(mut cx: FunctionContext) -> JsResult<BoxedPerson> {
let name = cx.argument::<JsString>(0)?.value(&mut cx);
let person = RefCell::new(Person::new(name));
Ok(cx.boxed(person))
}
fn person_set_name(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let person = cx.argument::<BoxedPerson>(0)?;
// Cannot borrow immutable local variable 'person' as mutable
let mut person = person.borrow_mut();
let name = cx.argument::<JsString>(1)?.value(&mut cx);
// no method named `set_name` found for mutable reference
// `&mut neon::handle::Handle<'_, neon::prelude::JsBox<std::cell::RefCell<Person>>>`
// in the current scope
person.set_name(name);
Ok(cx.undefined())
}
fn person_greet(mut cx: FunctionContext) -> JsResult<JsString> {
let person = cx.argument::<BoxedPerson>(0)?;
let person = person.borrow();
let greeting = person.greet();
Ok(cx.string(greeting))
}

I found a way around it by doing the following:
fn person_set_name(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let person = cx.argument::<BoxedPerson>(0)?;
let person = &*(*person);
let mut person = person.borrow_mut();
let name = cx.argument::<JsString>(1)?.value(&mut cx);
person.borrow_mut().set_name(name);
Ok(cx.undefined())
}

Related

Rust, returns a value referencing data owned by the current function

I checked forum for this question, I found some answers, but any of this situation was different and don't work for me.
I have problem with this error:
let test = PasswordHash::new(&hashed_password).clone().unwrap();
| ---------------- `hashed_password` is borrowed here
53 | // Ok(PasswordHash::new(&hashed_password).unwrap())
54 | Ok(test)
| ^^^^^^^^ returns a value referencing data owned by the current function
I exactly know what this error means. I know where the problem is, and I even know what provide it. But have no idea how can I fix it.
My idea it don't repeat part of code which is responsible for generating PasswordHash. I decided create separate function to do this.
My code below:
use argon2::{
password_hash::{
rand_core::OsRng,
PasswordHash, PasswordHasher, PasswordVerifier, SaltString, Error
},
Argon2,
};
struct AlgorithmData {
version: u32,
params: String,
algorithm_type: String,
}
impl AlgorithmData {
fn new() -> Self {
let example_string = "example_string";
let password_hash = Hasher::get_passwordhash_object(&example_string).unwrap();
AlgorithmData { version: password_hash.version.unwrap(),
params: password_hash.params.to_string(),
algorithm_type: password_hash.algorithm.to_string() }
}
}
pub struct Hasher {}
impl Hasher {
pub fn hash_string(string_to_hash: &str) -> Result<String, Error> {
let parsed_hash_password = Hasher::get_passwordhash_object(string_to_hash)?;
let result = format!("{}${}",
parsed_hash_password.salt.unwrap().to_string(),
parsed_hash_password.hash.unwrap().to_string());
Ok(result)
}
fn get_passwordhash_object(string_to_hash: &str) -> Result<PasswordHash, Error> {
let bytes_to_hash = string_to_hash.as_bytes();
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hashed_password = argon2.hash_password(&bytes_to_hash,
&salt)?.to_string();
let test = PasswordHash::new(&hashed_password).clone().unwrap();
// Ok(PasswordHash::new(&hashed_password).unwrap()) --> here too is problem
Ok(test) // here is the same problem
}
pub fn compare_string_to_hash(string_to_compare: &String,
hash_to_compare: &String) -> Result<bool, Error> {
let bytes_to_compare = string_to_compare.as_bytes();
let bytes_from_hash = PasswordHash::new(&hash_to_compare).unwrap();
Ok(Argon2::default().verify_password(&bytes_to_compare,
&bytes_from_hash).is_ok())
}
}
Like you see main problem is variable: hashed_password and it reference in new object PasswordHash.
I was tried use copy function to clone hashed_password variable or object PasswordHash.
Second thing was trying to use lifetime parameter like <'a>.
Third idea was using Box::new to try access to memory directly.
I need help to resolve this problem. I have already read documentation. But still have no more ideas to resolve this.
Error number: E0515 explaining reason quite well.
You definitely have a lifetime issue here. In your case, the PasswordHash lifetime depends on the SaltString. So, if you want to send a reference of PasswordHash out to the caller, it's better to take SaltString as an argument to the function get_passwordhash_object.
Here is the minimal example derived from your code:
use argon2::{
password_hash::{rand_core::OsRng, Error, PasswordHash, PasswordHasher, SaltString},
Argon2,
};
pub struct Hasher {}
impl Hasher {
fn get_passwordhash_object<'a>(
bytes_to_hash: &'a [u8],
salt: &'a SaltString,
) -> Result<PasswordHash<'a>, Error> {
let argon2 = Argon2::default();
let hashed_password = argon2.hash_password(&bytes_to_hash, salt).unwrap();
Ok(hashed_password)
}
}
fn main() {
let salt = SaltString::generate(&mut OsRng);
let hash = Hasher::get_passwordhash_object("something".as_bytes(), &salt);
println!("{:?}", hash);
}
If you check the documentation for PasswordHash::new you will see that it returns a struct with the same lifetime of the parameter. In your case the the test variable lifetime depends on the lifetime of hashed_password, that itself depends on the lifetime of salt, that owns its data.
In the get_passwordhash_object, you can't return PasswordHash type and discard the salt, you need to return both, or transform the data in something else that owns its data.
One solution is to serialize the PasswordHash into PasswordHashString, because this type owns his data
pub fn hash_string(string_to_hash: &str) -> Result<String, Error> {
let parsed_hash_password =
Hasher::get_passwordhash_object(string_to_hash)?;
let result = format!(
"{}${}",
parsed_hash_password.salt().unwrap().to_string(),
parsed_hash_password.hash().unwrap().to_string()
);
Ok(result)
}
fn get_passwordhash_object(
string_to_hash: &str,
) -> Result<PasswordHashString, Error> {
let bytes_to_hash = string_to_hash.as_bytes();
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hashed_password =
argon2.hash_password(&bytes_to_hash, &salt)?.to_string();
let test = PasswordHash::new(&hashed_password).clone().unwrap();
Ok(test.serialize())
}
pub fn compare_string_to_hash(
string_to_compare: &String,
hash_to_compare: &String,
) -> Result<bool, Error> {
let bytes_to_compare = string_to_compare.as_bytes();
let bytes_from_hash = PasswordHash::new(&hash_to_compare).unwrap();
Ok(Argon2::default()
.verify_password(&bytes_to_compare, &bytes_from_hash)
.is_ok())
}

Handling lifetimes when decoding generic types using SQLx

I am attempting to use a generic method to retrieve values from database tables that are structurally identical, but have different types for one of their columns. Simplified example below
async fn query<'a, 'r, T: DatabaseType<Item=T> + Decode<'r, Sqlite> + Type<Sqlite>>(&self, name: &'a str) -> Result<Vec<NamedValue<'a, T>>> {
let mut connection = self.pool.acquire().await?;
let mut rows = sqlx::query("Select id, value from table where name = $1")
.bind(name)
.fetch(&mut connection);
let mut results = Vec::new();
while let Some(row) = rows.try_next().await? {
results.push(NamedValue {
name,
value: row.try_get("value")?
})
}
Ok(results)
}
This will not compile, with the error: borrowed value does not live long enough, argument requires that 'row' is borrowed for 'r. The lifetime sqlx::Decode wants ('r), has to be declared as part of the query function's signature, but the resource the lifetime refers to does not exist yet, and only exists when the query executes and the stream is iterated over. I can't omit this bound on the generic, because the type does need to be decodable for try_get to work, so how do I tell the compiler that it is actually completely safe, and that the decoding is happening against a row that will definitely live longe enough for the try_get? Once the value is decoded, it will always have a static lifetime.
Rust playground doesn't include SQLx, an example that can be compiled at home is below:
[package]
name = "sqlx-minimal-example"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1", features = ["full"] }
sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "sqlite"] }
anyhow = "1.0"
futures = "0.3"
And the full application would be:
use anyhow::Result;
use sqlx::{Decode, Row, Sqlite, SqlitePool, Type};
use futures::TryStreamExt;
#[tokio::main]
async fn main() -> Result<()> {
println!("Hello, world!");
Ok(())
}
struct NamedValue<'a ,T> {
name: &'a str,
value: T
}
struct SqliteBackend {
pool: SqlitePool
}
trait DatabaseType {
type Item;
}
impl DatabaseType for f32 {
type Item = f32;
}
impl DatabaseType for i32 {
type Item = i32;
}
impl SqliteBackend {
async fn query<'a, 'r, T: DatabaseType<Item=T> + Decode<'r, Sqlite> + Type<Sqlite>>(&self, name: &'a str) -> Result<Vec<NamedValue<'a, T>>> {
let mut connection = self.pool.acquire().await?;
let mut rows = sqlx::query("Select id, value from table where name = $1")
.bind(name)
.fetch(&mut connection);
let mut results = Vec::new();
while let Some(row) = rows.try_next().await? {
results.push(NamedValue {
name,
value: row.try_get("value")?
})
}
Ok(results)
}
}
Higher-ranked trait bounds were the answer. This tells the compiler the type is decodable for all possible lifetimes.
Working function below:
async fn query<'a, T: DatabaseType<Item=T> + for<'r> Decode<'r, Sqlite> + Type<Sqlite>>(&self, name: &'a str) -> Result<Vec<NamedValue<'a, T>>> {
let mut connection = self.pool.acquire().await?;
let mut rows = sqlx::query("Select id, value from table where name = $1")
.bind(name)
.fetch(&mut connection);
let mut results = Vec::new();
while let Some(row) = rows.try_next().await? {
results.push(NamedValue {
name,
value: row.try_get("value")?
})
}
Ok(results)
}

Access Impl field from closure before field is alloc'ed in Rust?

I am new to Rust, as will probably be obvious.
Basically I have this scenario you can see below where, I create a new type that has a closure added to it, but this closure needs to access data which has not yet been created. The data will be created by the time the closure gets called, but when the closure is initially created the data is not yet available.
What is the best way to do deal with?
I am also curious if my closure was not a closure, but rather a private function in my implementation, how would I access that data? This closure/function is a callback from WasmTime and requires an explicit method signature which does not allow me to add $self to it. So how could I get at the instance fields of the implementation without a reference to $self in the function parameters?
pub struct EmWasmNode {
wasmStore: Store<WasiCtx>,
wasmTable: Table,
}
impl EmWasmNode {
pub fn new(filePath: &str) -> Result<Self> {
let engine = Engine::default();
// let module = Module::from_file(&engine, "wasm/index.wast")?;
let module = Module::from_file(&engine, filePath)?;
let mut linker = Linker::new(&engine);
wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;
let wasi = WasiCtxBuilder::new()
.inherit_stdio()
.inherit_args()?
.build();
let mut store = Store::new(&engine, wasi);
linker.func_wrap("env", "emscripten_set_main_loop", |p0: i32, p1: i32, p2: i32| {
println!("emscripten_set_main_loop {} {} {}", p0, p1, p2);
/*** How would I access wasmTable and wasmStore from here to execute more methods??? ***/
//let browserIterationFuncOption:Option<wasmtime::Val> = Self::wasmTable.get(&mut Self::wasmStore, p0 as u32);
// browserIterationFuncOption.unwrap().unwrap_funcref().call(&store, ());
})?;
let instance = linker.instantiate(&mut store, &module)?;
let table = instance
.get_export(&mut store, "__indirect_function_table")
.as_ref()
.and_then(extern_table)
.cloned();
let start = instance.get_typed_func::<(), (), _>(&mut store, "_start")?;
start.call(&mut store, ())?;
Ok(EmWasmNode {
wasmStore: store,
wasmTable: table.unwrap(),
})
}
You have to instantiate a struct before. I suggest the more simple code below to see my idea.
struct Atype
{
name: String,
}
impl Atype
{
pub fn new() -> Self
{
Self{ name: String::from("zeppi")}
}
pub fn test(&self) -> ()
{
let func = | x | { println!("{} {}", &self.name, x);};
func(3)
}
}
fn main() {
let o = Atype::new();
o.test();
}

Implementing Strategy pattern in rust without knowing which strategy are we using at compile time

I've been trying to implement a Strategy pattern in rust, but I'm having trouble understanding how to make it work.
So let's imagine we have a trait Adder and Element:
pub trait Element {
fn to_string(&self) -> String;
}
pub trait Adder {
type E: Element;
fn add (&self, a: &Self::E, b: &Self::E) -> Self::E;
}
And we have two implementations StringAdder with StringElements and UsizeAdder with UsizeElements:
// usize
pub struct UsizeElement {
pub value: usize
}
impl Element for UsizeElement {
fn to_string(&self) -> String {
self.value.to_string()
}
}
pub struct UsizeAdder {
}
impl Adder for UsizeAdder{
type E = UsizeElement;
fn add(&self, a: &UsizeElement, b: &UsizeElement) -> UsizeElement{
UsizeElement { value: a.value + b.value }
}
}
// String
pub struct StringElement {
pub value: String
}
impl Element for StringElement {
fn to_string(&self) -> String {
self.value.to_string()
}
}
pub struct StringAdder {
}
impl Adder for StringAdder {
type E = StringElement;
fn add(&self, a: &StringElement, b: &StringElement) -> StringElement {
let a: usize = a.value.parse().unwrap();
let b: usize = b.value.parse().unwrap();
StringElement {
value: (a + b).to_string()
}
}
}
And I want to write a code that uses trait methods from Adder trait and it's corresponding elements without knowing at compile time which strategy is going to be used.
fn main() {
let policy = "usize";
let element = "1";
let adder = get_adder(&policy);
let element_a = get_element(&policy, element);
let result = adder.add(element_a, element_a);
}
To simplify I'm going to assign a string to policy and element but normally that would be read from a file.
Is the only way to implement get_adder and get_element using dynamic dispatch? And by extension should I define Adder and Element traits to use trait objects and or the Any trait?
Edit: Here is what I managed to figure out so far.
An example of possible implementation is using match to help define concrete types for the compiler.
fn main() {
let policy = "string";
let element = "1";
let secret_key = "5";
let result = cesar(policy, element, secret_key);
dbg!(result.to_string());
}
fn cesar(policy: &str, element: &str, secret_key: &str) -> Box<dyn Element>{
match policy {
"usize" => {
let adder = UsizeAdder{};
let element = UsizeElement{ value: element.parse().unwrap() };
let secret_key = UsizeElement{ value: secret_key.parse().unwrap() };
Box::new(cesar_impl(&adder, &element, &secret_key))
}
"string" => {
let adder = StringAdder{};
let element = StringElement{ value: element.to_string() };
let secret_key = StringElement{ value: secret_key.to_string() };
Box::new(cesar_impl(&adder, &element, &secret_key))
}
_ => {
panic!("Policy not supported!")
}
}
}
fn cesar_impl<A>(adder: &A, element: &A::E, secret_key: &A::E) -> A::E where A: Adder, A::E : Element {
adder.add(&element, &secret_key)
}
However the issue is that I have to wrap every function I want to implement using a match function to determine the concrete type, and also case for every policy available.
It does not seem like the proper way of implementing it as it will bloat the code, make it more error prone and less maintainable unless I end up using macros.
Edit 2: Here you can find an example using dynamic dispatch. However I'm not convinced it's the proper way to implement the solution.
Example using dynamic dispatch
Thank you for your help :)

How do I use PickleDB with Rocket/Juniper Context?

I'm trying to write a Rocket / Juniper / Rust based GraphQL Server using PickleDB - an in-memory key/value store.
The pickle db is created / loaded at the start and given to rocket to manage:
fn rocket() -> Rocket {
let pickle_path = var_os(String::from("PICKLE_PATH")).unwrap_or(OsString::from("pickle.db"));
let pickle_db_dump_policy = PickleDbDumpPolicy::PeriodicDump(Duration::from_secs(120));
let pickle_serialization_method = SerializationMethod::Bin;
let pickle_db: PickleDb = match Path::new(&pickle_path).exists() {
false => PickleDb::new(pickle_path, pickle_db_dump_policy, pickle_serialization_method),
true => PickleDb::load(pickle_path, pickle_db_dump_policy, pickle_serialization_method).unwrap(),
};
rocket::ignite()
.manage(Schema::new(Query, Mutation))
.manage(pickle_db)
.mount(
"/",
routes![graphiql, get_graphql_handler, post_graphql_handler],
)
}
And I want to retrieve the PickleDb instance from the Rocket State in my Guard:
pub struct Context {
pickle_db: PickleDb,
}
impl juniper::Context for Context {}
impl<'a, 'r> FromRequest<'a, 'r> for Context {
type Error = ();
fn from_request(_request: &'a Request<'r>) -> request::Outcome<Context, ()> {
let pickle_db = _request.guard::<State<PickleDb>>()?.inner();
Outcome::Success(Context { pickle_db })
}
}
This does not work because the State only gives me a reference:
26 | Outcome::Success(Context { pickle_db })
| ^^^^^^^^^ expected struct `pickledb::pickledb::PickleDb`, found `&pickledb::pickledb::PickleDb`
When I change my Context struct to contain a reference I get lifetime issues which I'm not yet familiar with:
15 | pickle_db: &PickleDb,
| ^ expected named lifetime parameter
I tried using 'static which does make rust quite unhappy and I tried to use the request lifetime (?) 'r of the FromRequest, but that does not really work either...
How do I get this to work? As I'm quite new in rust, is this the right way to do things?
I finally have a solution, although the need for unsafe indicates it is sub-optimal :)
#![allow(unsafe_code)]
use pickledb::{PickleDb, PickleDbDumpPolicy, SerializationMethod};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::env;
use std::path::Path;
use std::time::Duration;
pub static mut PICKLE_DB: Option<PickleDb> = None;
pub fn cache_init() {
let pickle_path = env::var(String::from("PICKLE_PATH")).unwrap_or(String::from("pickle.db"));
let pickle_db_dump_policy = PickleDbDumpPolicy::PeriodicDump(Duration::from_secs(120));
let pickle_serialization_method = SerializationMethod::Json;
let pickle_db = match Path::new(&pickle_path).exists() {
false => PickleDb::new(
pickle_path,
pickle_db_dump_policy,
pickle_serialization_method,
),
true => PickleDb::load(
pickle_path,
pickle_db_dump_policy,
pickle_serialization_method,
)
.unwrap(),
};
unsafe {
PICKLE_DB = Some(pickle_db);
}
}
pub fn cache_get<V>(key: &str) -> Option<V>
where
V: DeserializeOwned + std::fmt::Debug,
{
unsafe {
let pickle_db = PICKLE_DB
.as_ref()
.expect("cache uninitialized - call cache_init()");
pickle_db.get::<V>(key)
}
}
pub fn cache_set<V>(key: &str, value: &V) -> Result<(), pickledb::error::Error>
where
V: Serialize,
{
unsafe {
let pickle_db = PICKLE_DB
.as_mut()
.expect("cache uninitialized - call cache_init()");
pickle_db.set::<V>(key, value)?;
Ok(())
}
}
This can be simply imported and used as expected, but I think I'll run into issues when the load gets to high...

Resources