I'm creating a simple app with rust and wasm-bindgen. I want to be able to call the initialize function from javascript, call functions to control the state from the rust program, and then get a value from the state with a function. I cannot pass the entire struct, it isn't thread safe or able to be serialized.
Here's a simplified example of what I would want
use wasm_bindgen::prelude::*
#[wasm_bindgen]
pub fn initialize_state(value: i32) {
state = State { a_value: value };
}
#[wasm_bindgen]
pub fn increment_value() {
state.a_value += 1;
}
#[wasm_bindgen]
pub fn get_value() -> i32 {
state.a_value
}
struct State {
a_value: i32,
}
I tried using lazy static and some other tricks to create a global variable for this, but I couldn't figure it out.
Eventually I ended up with this. It's unsafe, but it seems to work
use wasm_bindgen::prelude::*;
static mut STATE: *mut State = std::ptr::null_mut::<State>();
#[wasm_bindgen]
pub fn initialize_state(value: i32) {
unsafe {
STATE = Box::leak(Box::new(State { a_value: value }));
}
}
#[wasm_bindgen]
pub fn increment_value() {
unsafe {
(*STATE).a_value += 1;
}
}
#[wasm_bindgen]
pub fn get_value() -> i32 {
unsafe { (*STATE).a_value }
}
struct State {
a_value: i32,
}
Is there a way of doing this safely?
Related
Let's say I have a mutable structure (i32 in the example code for simplicity) which should be shared between threads. I can use Mutex for it (and Arc for memory management). But I want to have RAII wrapper for data lock to make some specific interface of data modification, track unlocks etc.
Here the draft (I don't know which lifetime specify for MutexGuard):
use std::sync::{Arc, Mutex, MutexGuard};
pub struct SharedData {
data: Arc<Mutex<i32>>
}
impl SharedData {
pub fn new(value: i32) -> Self {
SharedData {
data: Arc::new(Mutex::new(value))
}
}
pub fn lock(&self) -> LockedSharedData<'_> {
LockedSharedData::new(self.data.clone())
}
}
pub struct LockedSharedData<'a> {
_data: Arc<Mutex<i32>>,
guard: MutexGuard<'a, i32>
}
impl<'a> LockedSharedData<'a> {
fn new(data: Arc<Mutex<i32>>) -> Self {
LockedSharedData {
guard: data.lock().unwrap(),
_data: data
}
}
pub fn get(&self) -> i32 {
*self.guard
}
pub fn inc(&mut self) {
*self.guard += 1;
}
}
It predictable doesn't compile - https://rust.godbolt.org/z/4rEe3fWxK.
How to fix this pattern implementation?
In one of my projects, I would like to store a function pointer used as a callback to change the state of a struct. I've tried different things, but always encountered errors.
Consider the following situation (playground):
struct CallbackStruct {
callback: fn(i32) -> i32,
}
struct MainStruct {
pub callback_struct: Vec<CallbackStruct>,
pub intern_state: i32,
}
impl MainStruct {
pub fn new() -> MainStruct {
let result = MainStruct {
callback_struct: Vec::new(),
intern_state: 0,
};
// push a new call back struct
result.callback_struct.push(CallbackStruct{callback: result.do_stuff});
return result;
}
pub fn do_stuff(&mut self, i: i32) -> i32 {
self.intern_state = i * 2 + 1;
self.intern_state
}
}
fn main() {
let my_struct = MainStruct::new();
}
Here, I'm trying to keep a callback to the MainStruct, that can change it's internal state. This callback will only be stored by other structs owned by this main structure, so I don't think I'm having lifetimes issues - as long as the callback exists, the main struct does as well as it kind of own it.
Now, I'm wondering if having such a callback (with the &mut self reference) isn't a borrow of the main struct, preventing me from having multiple of them, or even keeping them?
In the example, I'm keeping a Vec of the CallbackStruct because I may have different structs all having these kinds of callbacks.
In c/c++, I can go with functions pointers, and I couldn't find a way to store such things in Rust.
How would one implement such a thing?
The problem that Rust is preventing is the possibility that being able to mutate the struct that holds the callback allows you to mutate or destroy the callback while it is executing. That is a problem.
If it is a common pattern that you want your callbacks to modify the structure that invokes the callback, then there's a couple options. Both require adjusting the function signature to pass-in data they are allowed to mutate. This would also allow multiple callbacks to mutate the same state since they only hold the mutable reference while they are running.
#1: Keep the state and callbacks separate
The idea is that the callback is explicitly given mutable access to the state which does not include the callback itself. This can be done by constructing a separate structure to hold the non-callback data, as shown here, or you can simply pass in multiple parameters:
struct InternalState(i32);
impl InternalState {
fn do_stuff(&mut self, i: i32) {
self.0 = i * 2 + 1;
}
}
struct MainStruct {
callbacks: Vec<Box<dyn FnMut(&mut InternalState)>>,
state: InternalState,
}
impl MainStruct {
fn new() -> MainStruct {
MainStruct {
callbacks: Vec::new(),
state: InternalState(0),
}
}
fn push(&mut self, f: Box<dyn FnMut(&mut InternalState)>) {
self.callbacks.push(f);
}
fn invoke(&mut self) {
for callback in &mut self.callbacks {
callback(&mut self.state)
}
}
}
fn main() {
let mut my_struct = MainStruct::new();
my_struct.push(Box::new(|state| { state.do_stuff(1); }));
my_struct.push(Box::new(|state| { state.do_stuff(2); }));
my_struct.invoke();
dbg!(my_struct.state.0);
}
#2 Remove the callback from the struct before executing it
You can mutate the whole struct itself if you remove the callback being ran. This can be done via the take-and-replace method used in this question. This has the added benefit that you have the opportunity to add new callbacks; you just have to reconcile the two sets of callbacks when putting them back:
struct InternalState(i32);
impl InternalState {
fn do_stuff(&mut self, i: i32) {
self.0 = i * 2 + 1;
}
}
struct MainStruct {
callbacks: Vec<Box<dyn FnMut(&mut MainStruct)>>,
state: InternalState,
}
impl MainStruct {
fn new() -> MainStruct {
MainStruct {
callbacks: Vec::new(),
state: InternalState(0),
}
}
fn push(&mut self, f: Box<dyn FnMut(&mut MainStruct)>) {
self.callbacks.push(f);
}
fn invoke(&mut self) {
let mut callbacks = std::mem::take(&mut self.callbacks);
for callback in &mut callbacks {
callback(self)
}
self.callbacks = callbacks;
}
}
fn main() {
let mut my_struct = MainStruct::new();
my_struct.push(Box::new(|main| { main.state.do_stuff(1); }));
my_struct.push(Box::new(|main| { main.state.do_stuff(2); }));
my_struct.invoke();
dbg!(my_struct.state.0);
}
You'll also noticed I changed the code from function pointers fn(i32) -> i32 to function trait objects Box<dyn FnMut(i32) -> i32> since the latter is much more flexible and common since it can actually capture other variables if needed.
I have a code like this from the offical tutorial book Chapter 9.3
#![allow(unused)]
fn main() {
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
pub fn value(&self) -> i32 {
self.value
}
}
let g = Guess{
value:1000
};
println!("{}", g.value);
}
According to the book I should not be able to create a Guess using the let g = Guess {} However, this code does not cause any error and prints 1000
There is still a problem even if I put the struct and impl outside the main func like this and delete the pub keyword.
struct Guess {}
impl Guess {}
fn main() {}
According to the book I should not be able to create a Guess using the let g = Guess {}
It is unlikely that the book states that.
Rust visibility works in terms of modules, anything in a module can see all the contents of their parents regardless of their pub status; the reverse is not true.
Since main and Guess.value are in the same module, there is no barrier. Moving Guess out of main doesn't change that, they're still in the same module. For visibility to become an issue, Guess needs to be moved into a separate non-ancestor module (e.g. a sub-module, or a sibling).
Example:
pub struct Foo(usize);
pub mod x {
pub struct Bar(usize);
impl Bar {
pub fn get(&self) -> usize { self.0 }
}
pub fn make(n: super::Foo) -> Bar {
// can access Foo's fields because this is a
// descendant module, so it is "part of" the
// same module
Bar(n.0)
}
}
pub fn qux(n: x::Bar) -> Foo {
// Can't access Bar's field because it's not exposed to this module
// Foo(n.0)
Foo(n.get())
}
I was playing around with updating a Rust struct in place using chained methods. I found a way to do this, but I was not sure if my code below was idiomatic Rust versus just a workaround.
In particular, I used .to_owned() at the end of the chained method to return the borrowed struct. The code compiles and works just fine. Here is the minimal example.
//struct.rs
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ModelDataCapture {
run: i32,
year: i32,
}
impl ModelDataCapture {
pub fn new() -> Self {
ModelDataCapture::default()
}
pub fn set_run(&mut self, run: i32) -> &mut ModelDataCapture {
self.run = run;
self
}
pub fn set_year(&mut self, year: i32) -> &mut ModelDataCapture {
self.year = year;
self
}
}
//main.rs
let data_capture = ModelDataCapture::new()
.set_run(0)
.set_year(1)
.to_owned(); // <<< QUESTION
println!("here is the data capture {:?}", data_capture);
Is this the proper way to write this in-place modification of the struct? If I do not include the .to_owned() method at the end of the chain, the compile fails with a message that the temporary variable does not live long enough.
Your code "works" but doesn't make sense to me. It:
Creates a value
Mutates the value
Clones the value
Throws away the original value
See the inefficiency? In addition, all the "in-place mutation" is completely discarded, so there's no benefit to it.
I'd generally introduce a binding to mutate:
let mut data_capture = ModelDataCapture::new();
data_capture.set_run(0).set_year(1);
Or go all the way and create a builder that has some equivalent of finish or build
#[derive(Debug)]
struct ModelDataCapture {
run: i32,
year: i32,
}
#[derive(Debug, Default)]
struct ModelDataCaptureBuilder {
run: i32,
year: i32,
}
impl ModelDataCaptureBuilder {
fn set_run(self, run: i32) -> Self {
ModelDataCaptureBuilder { run, ..self }
}
fn set_year(self, year: i32) -> Self {
ModelDataCaptureBuilder { year, ..self }
}
fn build(self) -> ModelDataCapture {
let ModelDataCaptureBuilder { run, year } = self;
ModelDataCapture { run, year }
}
}
fn main() {
let data_capture = ModelDataCaptureBuilder::default().set_run(0).set_year(1).build();
println!("here is the data capture {:?}", data_capture);
}
See Do Rust builder patterns have to use redundant struct code? for more examples of builders that mirror the built items.
You could take self by-value in the first example, but that's annoying in most cases, as you always have to remember to bind the result.
You could change the function to take ownership over self and return self.
Because each "setter" method returns the ownership of self, this code should work out nicely.
For more information, please checkout the rust book
//struct.rs
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ModelDataCapture {
run: i32,
year: i32,
}
impl ModelDataCapture {
pub fn new() -> Self {
ModelDataCapture::default()
}
pub fn set_run(mut self, run: i32) -> ModelDataCapture {
self.run = run;
self
}
pub fn set_year(mut self, year: i32) -> ModelDataCapture {
self.year = year;
self
}
}
fn main() {
//main.rs
let data_capture = ModelDataCapture::new().set_run(0).set_year(1);
println!("here is the data capture {:?}", data_capture);
}
I have a builder pattern implemented for my struct:
pub struct Struct {
pub grand_finals_modifier: bool,
}
impl Struct {
pub fn new() -> Struct {
Struct {
grand_finals_modifier: false,
}
}
pub fn grand_finals_modifier<'a>(&'a mut self, name: bool) -> &'a mut Struct {
self.grand_finals_modifier = grand_finals_modifier;
self
}
}
Is it possible in Rust to make a macro for methods like this to generalize and avoid a lot of duplicating code? Something that we can use as the following:
impl Struct {
builder_field!(hello, bool);
}
After reading the documentation, I've come up with this code:
macro_rules! builder_field {
($field:ident, $field_type:ty) => {
pub fn $field<'a>(&'a mut self,
$field: $field_type) -> &'a mut Self {
self.$field = $field;
self
}
};
}
struct Struct {
pub hello: bool,
}
impl Struct {
builder_field!(hello, bool);
}
fn main() {
let mut s = Struct {
hello: false,
};
s.hello(true);
println!("Struct hello is: {}", s.hello);
}
It does exactly what I need: creates a public builder method with specified name, specified member and type.
To complement the already accepted answer, since it is 4 years old by now, you should check out the crate rust-derive-builder. It uses procedural macros to automatically implement the builder pattern for any struct.