Rust fs read dir - rust

I am writing a program that read dir and then if there a dir it should read it
I have tried this code:
pub async fn list_folder() {
let program_data_folder = String::from(std::env::var("ProgramData").expect("err") + "/Microsoft/Windows/Start Menu/Programs");
let path = Path::new(&program_data_folder);
let paths = fs::read_dir(path).unwrap();
for folder in paths {
println!("Name: {}", folder.unwrap().path().display());
if folder.unwrap().path().is_dir() {
fs::read_dir(folder.unwrap().file_name()).unwrap();
}
}
}
Error:
use of moved value: `folder`
value used here after moverustcClick for full compiler diagnostic
listeners.rs(15, 37): `folder` moved due to this method call
listeners.rs(15, 30): help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
listeners.rs(14, 9): move occurs because `folder` has type `Result<DirEntry, std::io::Error>`, which does not implement the `Copy` trait
result.rs(1106, 19): `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `folder`
How can I fix it?

The key is the last line:
Result::<T, E>::unwrap takes ownership of the receiver self, which moves folder
After you unwrap a Result it's not usable any more because the Ok value's been moved out. That means you can't call unwrap() repeatedly.
To fix it, call unwrap() once and save the result, like so:
for folder in paths {
let folder = folder.unwrap();
println!("Name: {}", folder.path().display());
if folder.path().is_dir() {
fs::read_dir(folder.file_name()).unwrap();
}
}
Unwrapping everything is a bad habit, though. It means I/O errors crash the program immediately. It's a lot better to let errors propagate to the caller so it can deal with them however it chooses. This entails making your function return a Result and replacing all the unwraps with ?. Rust makes the best option, ?, the shortest, to encourage good error handling.
pub async fn list_folder() -> std::io::Result<()> {
let program_data_folder = String::from(std::env::var("ProgramData").expect("err") + "/Microsoft/Windows/Start Menu/Programs");
let path = Path::new(&program_data_folder);
let paths = fs::read_dir(path)?;
for folder in paths {
let folder = folder?;
println!("Name: {}", folder.path().display());
if folder.path().is_dir() {
fs::read_dir(folder.file_name())?;
}
}
Ok(())
}

Related

Moving something that is in scope of a reference when those references will go out of scope immediately after the move

I am learning Rust coming from a C++ background. I am writing a parser that reads valid formulas such as 12 x (y - 4) and puts them in an abstract syntax tree (AST). I use an enum to store the possible nodes in the AST as you can see in the (heavily simplified) code. I ran into a problem. I want to simplify the expression -(-(12)) for instance by moving the 12, not copying. In general the 12 may be replaced by a deep AST. Currently I identify the situation in the function simplify( .. ) but it wont compile.
I do know why it doesn't compile: The node I'm trying to move (i.e. the 12 in my example) is still in scope as a reference from in the match clause so this is exactly rust preventing me from a possible problem with references. But in my case I know this is what I want, and moreover I exit the function right after I do the moving in the line *node = **child;, so the earlier references will go out of scope right there.
Is there an idiomatic Rust-esque type of way to solve this problem? I would really rather not copy the double--negated subtree.
#[derive(Debug)]
enum Node {
Num(i32),
UnaryMinus(Box<Node>),
}
use Node::*;
fn simplify(node: &mut Node) {
match &node {
Num(_) => (),
UnaryMinus(inner) => match &**inner {
Num(_) => (),
UnaryMinus(child) => {
// cannot move out of `**child` which is behind a shared reference
*node = **child;
return;
}
},
}
}
fn main() {
let double_minus = UnaryMinus(Box::new(UnaryMinus(Box::new(Num(12)))));
}
There are two problems here: The error you're getting concretely is because you're matching against &**inner instead of &mut **inner. It's never okay to move out of a shared reference, but there are circumstances (which we'll see) when it's okay to move out of a mutable one.
With that fixed, you will get the same error just about mutable references. That's because you can't move out of a mutable reference just because you know you're the only one holding it. A move leaves its source uninitialized, and a reference, mutable or shared, to uninitialized memory is never okay. You'll have to leave something in that memory that you're moving out of. You can do that with std::mem::swap. It takes two mutable references and swaps out the contents.
Now, one could obviously try to call std::mem::swap(node, &mut child) but this won't work simply because node is already mutably borrowed in the match expression and you can't mutably borrow something twice.
Moreover, this would leak memory as you now have a reference cycle where node -> inner -> node. This, although perfectly valid to do in Rust, usually isn't what you want.
Instead you'll need some sort of dummy that you can put in child's place. Some simple variant of your enum that can be safely dropped by inner once it gets dropped. In this example that could be Node::Num(0):
#[derive(Debug)]
enum Node {
Num(i32),
UnaryMinus(Box<Node>),
}
// This is just to verify that everything gets dropped properly
// and we don't leak any memory
impl Drop for Node {
fn drop(&mut self) {
println!("dropping {:?}", self);
}
}
use Node::*;
fn simplify(node: &mut Node) {
// `placeholder` will be our dummy
let (mut can_simplify, mut placeholder) = (false, Num(0));
match node {
Num(_) => (),
// we'll need to borrow `child` mutably later, so we have to
// match on `&mut **inner` not `&**inner`
UnaryMinus(inner) => match &mut **inner {
Num(_) => (),
UnaryMinus(ref mut child) => {
// move the contents of `child` into `placeholder` and vice versa
std::mem::swap(&mut placeholder, child);
can_simplify = true;
}
},
}
if can_simplify {
// now we can safely move into `node`
*node = placeholder;
// you could skip the conditional if all other, non-simplifying
// branches return before this statement
}
}
fn main() {
let mut double_minus = UnaryMinus(Box::new(UnaryMinus(Box::new(Num(12)))));
simplify(&mut double_minus);
println!("{:?}", double_minus);
}

How do I define the lifetime for a tokio task spawned from a class?

I'm attempting to write a generic set_interval function helper:
pub fn set_interval<F, Fut>(mut f: F, dur: Duration)
where
F: Send + 'static + FnMut() -> Fut,
Fut: Future<Output = ()> + Send + 'static,
{
let mut interval = tokio::time::interval(dur);
tokio::spawn(async move {
// first tick is at 0ms
interval.tick().await;
loop {
interval.tick().await;
tokio::spawn(f());
}
});
}
This works fine until it's called from inside a class:
fn main() {}
struct Foo {}
impl Foo {
fn bar(&self) {
set_interval(|| self.task(), Duration::from_millis(1000));
}
async fn task(&self) {
}
}
self is not 'static, and we can't restrict lifetime parameter to something that is less than 'static because of tokio::task.
Is it possible to modify set_interval implementation so it works in cases like this?
Link to playground
P.S. Tried to
let instance = self.clone();
set_interval(move || instance.task(), Duration::from_millis(1000));
but I also get an error: error: captured variable cannot escape FnMut closure body
Is it possible to modify set_interval implementation so it works in cases like this?
Not really. Though spawn-ing f() really doesn't help either, as it precludes a simple "callback owns the object" solution (as you need either both callback and future to own the object, or just future).
I think that leaves two solutions:
Convert everything to shared mutability Arc, the callback owns one Arc, then on each tick it clones that and moves the clone into the future (the task method).
Have the future (task) acquire the object from some external source instead of being called on one, this way the intermediate callback doesn't need to do anything. Or the callback can do the acquiring and move that into the future, same diff.
Incidentally at this point it could make sense to just create the future directly, but allow cloning it. So instead of taking a callback set_interval would take a clonable future, and it would spawn() clones of its stored future instead of creating them anew.
As mentioned by #Masklinn, you can clone the Arc to allow for this. Note that cloning the Arc will not clone the underlying data, just the pointer, so it is generally OK to do so, and should not have a major impact on performance.
Here is an example. The following code will produce the error async block may outlive the current function, but it borrows data, which is owned by the current function:
fn main() {
// 🛑 Error: async block may outlive the current function, but it borrows data, which is owned by the current function
let data = Arc::new("Hello, World".to_string());
tokio::task::spawn(async {
println!("1: {}", data.len());
});
tokio::task::spawn(async {
println!("2: {}", data.len());
});
}
Rust unhelpfully suggests adding move to both async blocks, but that will result in a borrowing error because there would be multiple ownership.
To fix the problem, we can clone the Arc for each task and then add the move keyword to the async blocks:
fn main() {
let data = Arc::new("Hello, World".to_string());
let data_for_task_1 = data.clone();
tokio::task::spawn(async move {
println!("1: {}", data_for_task_1.len());
});
let data_for_task_2 = data.clone();
tokio::task::spawn(async move {
println!("2: {}", data_for_task_2.len());
});
}

Rust File Tree move occurs because `subtree` has type `trees::Tree<PathBuf>`, which does not implement the `Copy` trait

i am trying to make a simple tauri Program where i have a Filetree of all Files and sub files of a chosen directory.
I have not got many experience in Rust and ran into a problem with Ownerships.
Code
use std::fs;
use std::path::PathBuf;
use trees::Tree;
//FileTree
//https://docs.rs/crate/file_tree/0.1.1
fn main() {
let path = PathBuf::from("MyPath...");
let tree = Tree::new(path);
build_tree(tree);
}
fn build_tree( mut tree:Tree<PathBuf>){
let path = tree.front().unwrap().data();
for entry in fs::read_dir(path).unwrap() {
let entry = entry.unwrap();
let subpath = entry.path();
if subpath.is_dir() {
let subtree = Tree::new(subpath);
build_tree(subtree);
tree.push_back(subtree);
} else {
tree.push_back(Tree::new(subpath));
}
}
tree;
}
This is what i figured out so far but in the line:
tree.push_back(subtree);
I got following Error
error[E0382]: use of moved value: subtree
--> src\main.rs:23:28
|
21 | let subtree = Tree::new(subpath);
| ------- move occurs because `subtree` has type `trees::Tree<PathBuf>`, which does not implement the `Copy` trait
22 | build_tree(subtree);
| ------- value moved here
23 | tree.push_back(subtree);
| ^^^^^^^ value used here after move
What i tried
I tried to make subtree mutable but it didn't work either because it says mut is not necessary
Also i already tried to use the Filetree crate of Rust but it was not exectely what i was looking for.
Someone got other Ideas how to Implement a Filetree in Rust or Tauri?
You are trying to mutate a tree in your build_tree function, but since the function is taking ownership of whatever you pass in, you get the value used here after move error afterwards. To allow a function to mutate a variable and the variable still exist afterwards, you should instead pass in a mutable reference to the tree:
use std::fs;
use std::path::PathBuf;
use trees::Tree;
fn main() {
let path = PathBuf::from("MyPath...");
let mut tree = Tree::new(path);
build_tree(&mut tree);
}
fn build_tree(tree: &mut Tree<PathBuf>) {
let path = tree.front().unwrap().data();
for entry in fs::read_dir(path).unwrap() {
let entry = entry.unwrap();
let subpath = entry.path();
if subpath.is_dir() {
let mut subtree = Tree::new(subpath);
build_tree(&mut subtree);
tree.push_back(subtree);
} else {
tree.push_back(Tree::new(subpath));
}
}
}
Notice also that you need to change some variable declarations to use let mut so that the compiler allows a mutable reference (&mut) to that variable to be used.
This can also be done by taking ownership and returning a new value, but this method looks a little closer to what you had originally.

Safely move or dereference Receiver in a Fn?

I'm working on an app that optionally uses a GUI to display video data that's roughly structured like this:
fn main() {
let (window_tx, window_rx) =
MainContext::channel::<MyStruct>(PRIORITY_DEFAULT);
let some_thread = thread::spawn(move || -> () {
// send data to window_tx
});
let application =
gtk::Application::new(Some("com.my.app"), Default::default());
application.connect_activate(move |app: &gtk::Application| {
build_ui(app, window_rx);
});
application.run();
some_thread.join().unwrap();
}
fn build_ui(application: &gtk::Application, window_rx: Receiver<MyStruct>) {
window_rx.attach( ... );
}
The gtk rust library requires a Fn callback passed to application.connect_activate on startup, so I can't use a FnOnce or FnMut closure to move the glib::Receiver in the callback. The compiler throws this error:
error[E0507]: cannot move out of `window_rx`, a captured variable in an `Fn` closure
I've tried to avoid the move by wrapping window_rx in a Rc, ie:
let r = Rc::new(RefCell::new(window_rx));
application.connect_activate(move |app: &gtk::Application| {
build_ui(app, Rc::clone(&r));
});
But upon dereferencing the Rc in my build_ui function, I get this error:
error[E0507]: cannot move out of an `Rc`
The fallback I've used thus far is to just move the channel creation and thread creation into my build_ui function, but because the GUI is not required, I was hoping to avoid using GTK and the callback entirely if GUI is not used. Is there some way I can either safely move window_rx within a closure or otherwise dereference it in the callback without causing an error?
When you need to move a value out from code that, by the type system but not in practice, could be called more than once, the simple tool to reach for is Option. Wrapping the value in an Option allows it to be swapped with an Option::None.
When you need something to be mutable even though you're inside a Fn, you need interior mutability; in this case, Cell will do. Here's a complete compilable program that approximates your situation:
use std::cell::Cell;
// Placeholders to let it compile
use std::sync::mpsc;
fn wants_fn_callback<F>(_f: F) where F: Fn() + 'static {}
struct MyStruct;
fn main() {
let (_, window_rx) = mpsc::channel::<MyStruct>();
let window_rx: Cell<Option<mpsc::Receiver<MyStruct>>> = Cell::new(Some(window_rx));
wants_fn_callback(move || {
let _: mpsc::Receiver<MyStruct> = window_rx.take().expect("oops, called twice");
});
}
Cell::take() removes the Option<Receiver> from the Cell, leaving None in its place. The expect then removes the Option wrapper (and handles the possibility of the function being called twice by panicking in that case).
Applied to your original problem, this would be:
let window_rx: Option<Receiver<MyStruct>> = Cell::new(Some(window_rx));
application.connect_activate(move |app: &gtk::Application| {
build_ui(app, window_rx.take().expect("oops, called twice"));
});
However, be careful: if the library requires a Fn closure, there might be some condition under which the function could be called more than once, in which case you should be prepared to do something appropriate in that circumstance. If there isn't such a condition, then the library's API should be improved to take a FnOnce instead.

Discerning lifetimes understanding the move keyword

I've been playing around with AudioUnit via Rust and the Rust library coreaudio-rs. Their example seems to work well:
extern crate coreaudio;
use coreaudio::audio_unit::{AudioUnit, IOType};
use coreaudio::audio_unit::render_callback::{self, data};
use std::f32::consts::PI;
struct Iter {
value: f32,
}
impl Iterator for Iter {
type Item = [f32; 2];
fn next(&mut self) -> Option<[f32; 2]> {
self.value += 440.0 / 44_100.0;
let amp = (self.value * PI * 2.0).sin() as f32 * 0.15;
Some([amp, amp])
}
}
fn main() {
run().unwrap()
}
fn run() -> Result<(), coreaudio::Error> {
// 440hz sine wave generator.
let mut samples = Iter { value: 0.0 };
//let buf: Vec<[f32; 2]> = vec![[0.0, 0.0]];
//let mut samples = buf.iter();
// Construct an Output audio unit that delivers audio to the default output device.
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
// Q: What is this type?
let callback = move |args| {
let Args { num_frames, mut data, .. } = args;
for i in 0..num_frames {
let sample = samples.next().unwrap();
for (channel_idx, channel) in data.channels_mut().enumerate() {
channel[i] = sample[channel_idx];
}
}
Ok(())
};
type Args = render_callback::Args<data::NonInterleaved<f32>>;
try!(audio_unit.set_render_callback(callback));
try!(audio_unit.start());
std::thread::sleep(std::time::Duration::from_millis(30000));
Ok(())
}
However, changing it up a little bit to load via a buffer doesn't work as well:
extern crate coreaudio;
use coreaudio::audio_unit::{AudioUnit, IOType};
use coreaudio::audio_unit::render_callback::{self, data};
fn main() {
run().unwrap()
}
fn run() -> Result<(), coreaudio::Error> {
let buf: Vec<[f32; 2]> = vec![[0.0, 0.0]];
let mut samples = buf.iter();
// Construct an Output audio unit that delivers audio to the default output device.
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
// Q: What is this type?
let callback = move |args| {
let Args { num_frames, mut data, .. } = args;
for i in 0..num_frames {
let sample = samples.next().unwrap();
for (channel_idx, channel) in data.channels_mut().enumerate() {
channel[i] = sample[channel_idx];
}
}
Ok(())
};
type Args = render_callback::Args<data::NonInterleaved<f32>>;
try!(audio_unit.set_render_callback(callback));
try!(audio_unit.start());
std::thread::sleep(std::time::Duration::from_millis(30000));
Ok(())
}
It says, correctly so, that buf only lives until the end of run and does not live long enough for the audio unit—which makes sense, because "borrowed value must be valid for the static lifetime...".
In any case, that doesn't bother me; I can modify the iterator to load and read from the buffer just fine. However, it does raise some questions:
Why does the Iter { value: 0.0 } have the 'static lifetime?
If it doesn't have the 'static lifetime, why does it say the borrowed value must be valid for the 'static lifetime?
If it does have the 'static lifetime, why? It seems like it would be on the heap and closed on by callback.
I understand that the move keyword allows moving inside the closure, which doesn't help me understand why it interacts with lifetimes. Why can't it move the buffer? Do I have to move both the buffer and the iterator into the closure? How would I do that?
Over all this, how do I figure out the expected lifetime without trying to be a compiler myself? It doesn't seem like guessing and compiling is always a straightforward method to resolving these issues.
Why does the Iter { value: 0.0 } have the 'static lifetime?
It doesn't; only references have lifetimes.
why does it say the borrowed value must be valid for the 'static lifetime
how do I figure out the expected lifetime without trying to be a compiler myself
Read the documentation; it tells you the restriction:
fn set_render_callback<F, D>(&mut self, f: F) -> Result<(), Error>
where
F: FnMut(Args<D>) -> Result<(), ()> + 'static, // <====
D: Data
This restriction means that any references inside of F must live at least as long as the 'static lifetime. Having no references is also acceptable.
All type and lifetime restrictions are expressed at the function boundary — this is a hard rule of Rust.
I understand that the move keyword allows moving inside the closure, which doesn't help me understand why it interacts with lifetimes.
The only thing that the move keyword does is force every variable directly used in the closure to be moved into the closure. Otherwise, the compiler tries to be conservative and move in references/mutable references/values based on the usage inside the closure.
Why can't it move the buffer?
The variable buf is never used inside the closure.
Do I have to move both the buffer and the iterator into the closure? How would I do that?
By creating the iterator inside the closure. Now buf is used inside the closure and will be moved:
let callback = move |args| {
let mut samples = buf.iter();
// ...
}
It doesn't seem like guessing and compiling is always a straightforward method to resolving these issues.
Sometimes it is, and sometimes you have to think about why you believe the code to be correct and why the compiler states it isn't and come to an understanding.

Resources