This question already has answers here:
How do I synchronously return a value calculated in an asynchronous Future?
(3 answers)
Closed 2 years ago.
Rust newbie here (<7 days into learning), the second hurdle I am trying to overcome after ownership rule is async/await.
I am writing a test that calls an async function and I need to get the result from the Future without using the keyword await.
I have looked at async_test, however I can't use that because (as I understand) this requires tokio runtime and #[tokio_main] attribute in my main method - but I have my main already decorated with #[actix_rt::main]
This is my test
#[test]
pub fn test_get_item() -> Result<(), anyhow::Error> {
let c = SomeClient::new();
let result = c.get_item(123456).await?; // <- this is not allowed
assert_eq!("Hello", result.title);
assert_eq!("https://example.com", result.url.as_str());
Ok(())
}
Things I have tried and failed (mostly due to my lack of knowledge in Rust)
Use async_test on an actix web project using futures-await-test crate.
Read this thread in reddit.
Follow few examples from this rust community thread
Tried to poll() the future but it didn't lead me anywhere.
I don't understand why this has to be so complicated, maybe there is a simple function (like wait() or get_result()) somewhere for Future?
Thanks for your help.
Had to clear my head for a bit and start again, just to find actix-web has a macro I can use that allows async tests.
#[actix_rt::test]
Macros are all magic to me at this point, I hope I;ll understand them soon.
Related
This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Closed 2 months ago.
I just have started learning Rust. While going to some of its examples, I could not understand behaviour of references (Which I loosely relate with pointers).
fn main(){
let mut s = String::from("abc");
DoStuff(&mut s);
}
fn DoStuff(reff : &mut String){
reff.push_str("xyz");
(*reff).push_str("xyz");
// In the above two lines, why they perform similar actions?
// as reff and *reff are different types.
// *reff should only be able to call pust.str(). But how reff can also call it?
// reff = String::from("dsf"); --> Why this will give compile error
// if reff & (*reff) behaves somewhat similar for us
}
In the above example,
both lines
reff.push_str("xyz");
(*reff).push_str("xyz");
act similar.
As, pust_str() is a method from String. Only (*reff) should be able to call it as per my understanding. Still, reff is also able to call it.
How can I understand this unexpected behaviour?
Types that implement the Deref trait do automatic dereferencing.
Mostly so you don't have to write (*reff). all the time.
I have an async fn that returns a type, and want to implement Drop on that type that calls another async function. It's not clear how to do this, and I can't find anything in the docs. The most illuminating article I found is Asynchronous Destructors by withoutboats, but I don't really understand the reasoning, or where this feature is at.
It's not clear how to do this, and I can't find anything in the docs
That's because it's not possible; there is no "async Drop". Drop must be synchronous.
See also:
How do I synchronously return a value calculated in an asynchronous Future in stable Rust?
When building async futures, it's common to implement the ArcWake trait in wakers. I understand this is done to avoid writing boilerplate, creating vtables and writing unsafe code (according to the tokio tutorial).
Now, (and this feels like a silly question) what I don't understand is how does implementing a trait avoid writing that other code? When I check the source of the trait, it contains practically nothing: only the declaration of one small function that needs to be implemented to fulfil the trait and the instantiation of another function that calls that one. So, where are all those things we're avoiding writing coming from? Where's the boilerplate, vtables, unsafe code and all that and how does it get executed just because we implemented a trait on a waker?
OK, I think I got it now. The code I couldn't find is here (thanks for the comment on the question that pointed this out!). That code is all called on the tutorial when the future is polled, specifically on the line
let waker = task::waker(self.clone());
On this line, we're obtaining a waker from an ArcWake by calling the task::waker function which deals with all the complexity for us.
When providing callbacks to JavaScript using Closures, what's a better way to deal with avoiding freeing them? The wasm-bindgen guide suggests using .forget, but admits that that is essentially leaking memory.
Normally we'd store the handle to later get dropped at an appropriate time but for now we want it to be a global handler so we use the forget method to drop it without invalidating the closure. Note that this is leaking memory in Rust, so this should be done judiciously!
It hints at storing the closure until a time when it's appropriate to be dropped. In alexcrichton's answer to a previous question, he mentions...
[...] if it's [...] only invoked once, then you can use Rc/RefCell to drop the Closure inside the the closure itself (using some interior mutability shenanigans)
But he doesn't provide an example of this method.
The Closure documentation also gives an example of returning the reference to the closure to the JavaScript context to let it handle when to free the reference.
If we were to drop cb here it would cause an exception to be raised whenever the interval elapses. Instead we return our handle back to JS so JS can decide when to cancel the interval and deallocate the closure.
I'd also imagine there are ways to use features like lifetimes or the #[wasm_bindgen] macro on a public function to avoid this issue as well, but I'm having trouble figuring out how to do it that way.
My question is, what are the alternatives to using .forget with closures that are being passed back to JavaScript from Rust, and can I please see some simple examples of each option in use?
I recently built a small commercial app and was stuck on this for weeks and was really excited when I got this working. I ended up using Closure.once_into_js. However, that also has the caveat that "The only way the FnOnce is deallocated is by calling the JavaScript function. If the JavaScript function is never called then the FnOnce and everything it closes over will leak." So if the callback is called, everything should be fine, but if not, there is still a memory leak. I found the programming style to be pretty nice. I mapped the JavaScript functions to Rust like this:
#[wasm_bindgen]
fn getSomething(details: &JsValue, callback: JsValue);
pub fn get_something(details: &Details, callback: impl Fn(Option<String>) + 'static){
getSomething(&serde_wasm_bindgen::to_value(details).unwrap(), Closure::once_into_js(move |v: JsValue|
callback(serde_wasm_bindgen::from_value(v).unwrap())
));
}
And then I'm able to use it from Rust in my app like so:
let callback = move |id| {
};
get_something(&details, callback);
I defined the callbacks as static impl functions and then move the values in.
This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Shared circular references in Rust
(1 answer)
Closed 3 years ago.
I am learning Rust from a C++/Java background, and I have the following pattern
struct Node<'a> {
network_manager: NetworkManager<'a>,
}
struct NetworkManager<'a> {
base_node: &'a Node<'a>,
}
The node contains the threadpool that the NetworkManager uses to "handoff" messages once they've been processed. Because of the recursive call, it is not possible to set the base_node field in the NetworkManager immediately. In Java, I would leave it as null and have a second method that is called after the constructor called initialise(BaseNode node) that would set the base_node field (ensuring that there are no calls to the network manager before initialise is called).
What is the idiomatic way of doing this in Rust? The only way I can think of is to make base_node an Option type, but this seems suboptimal.
In general, what is the "right" way in Rust to deal with situations where A points to B and B points to A, and where (as in my case), refactoring is not possible?
From my experience, these situations are very different from other languages. In "safe, simple, everyday Rust" having backpointers/pointers within the struct is complex since it leads to non-trivial problems. (Consider what would happen if you would move Node around in memory: How would you properly update the backpointer in NetworkManager?)
What I usually resort to is simply passing base_node as a parameter to the functions that need the backpointer. This is sometimes easier said than done, but leads to code that clearly states ownership.