#fs::read_dir try

31 messages · Page 1 of 1 (latest)

fervent hinge
#

i'm making a file tool in rust with tauri.

i'm new to low level programing, i have done very little in c (never any async or sys functions).

i want to enumerate all the files in a directory. and get their absolute path respectively.
i followed the example but it doesn't like it.

async fn visit_directory(app_handle: &tauri::AppHandle, dir: &Path) -> Result<DirectoryResult, ()> {
  let mut file_count = 0;
  for entry in  fs::read_dir(dir) {
    let path = entry.path();
    println!("{}", path.display());
    if path.is_dir() {

error:

error[E0599]: no method named `path` found for struct `ReadDir` in the current scope
  --> src\main.rs:26:22
   |
26 |     let path = entry.path();
   |                      ^^^^ method not found in `ReadDir`
#

all the different manipulations you have to make and when you do it it doesn't like that either. are really difficult for me because i live in ts,lua, and python.

runic creek
#

There's a couple of places where you have Result types...if you look at the example they handle them with the ? operator to propagate the errors but you can replace ? With .unwrap() if you don't care about handling the error

fervent hinge
#

i did, but it yells at me because it dropps something temporatliy then borrowed agian.

#

idk

runic creek
#

Better to take only one error at a time, first thing would be to try to make your code the same or similar to the example (using either the ? operator, or using .unwrap instead of it which is fine for learning purposes and prototyping)

After that we take a look at the next error

#

The good thing is that these errors you're getting are something you can fix before you can even get to run your code....in the js, python, etc. you're coming from those errors would only show up when it hits that code path at runtime

So takes a little more to learn these things, being careful with types and such but more reliable code in the end

fervent hinge
#

i meant to say ts, i use typescript a lot.

runic creek
#

Okay, that's good then in that case you know about strongly typed languages (from what I understand.....I've never used typescript....it's strongly typed that compiles to JavaScript so dealing with the correct types is something you have to do there too)

In that case the new stuff Rust will bring will be things like the borrow checker, and also the fact that type conversations are more explicit than other languages

#

(and this ? operator in the examples is probably new to you too)

fervent hinge
#
error[E0277]: `?` couldn't convert the error to `()`
  --> src\main.rs:26:22
   |
26 |     let entry = entry?;
   |                      ^ the trait `From<std::io::Error>` is not implemented for `()`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
error[E0277]: `?` couldn't convert the error to `()`
  --> src\main.rs:25:33
   |
25 |   for entry in fs::read_dir(dir)? {
   |                                 ^ the trait `From<std::io::Error>` is not implemented for `()`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait 
runic creek
#

Yeah, so if you look at your function signature here, the "Error" type of your Result is () where you're returning Result<DirectoryResult, ()>

The type you're applying the ? Operator to is a Result with the error type of std::io::Error though

The operator will try to convert the error type you have (std::io::Error) into the error type you wanted to return (())

It can only do this if such a conversion exists though (the From trait is implemented to construct one from the other)

() Doesn't implement Fromstd::io::Error though so this isn't possible

What you're probably wanting to do is to change your function to return Result<DirectoryResult, std::io::Error> instead

fervent hinge
#

ohhhh

#
async fn visit_directory(app_handle: &tauri::AppHandle, dir: PathBuf) -> Result<DirectoryResult, Error> {
  let mut file_count = 0;
  for entry in fs::read_dir(dir)? {
    let entry = entry?;
    let path = entry.path();
error[E0733]: recursion in an `async fn` requires boxing
  --> src\main.rs:24:74
   |
24 | async fn visit_directory(app_handle: &tauri::AppHandle, dir: PathBuf) -> Result<DirectoryResult, Error> {
   |                                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
   |
   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
runic creek
#

async has it's own problems which explains why your code hits this while the example doesn't (that's not async)

Luckily as with most errors the compiler often gives you hints on how to fix it, in this case directing you toward a crate that gives you a macro you can just slap on the function

https://docs.rs/async-recursion/latest/async_recursion/

fervent hinge
#

why does cargo do this?
warning: spurious network error (3 tries remaining): [6] Couldn't resolve host name

#

i have to run it like 3 time

#

it works!

#

thx

#

how do you fix this?

error[E0716]: temporary value dropped while borrowed
  --> src\main.rs:31:16
   |
31 |     let path = entry.path().as_path();
   |                ^^^^^^^^^^^^^^          - temporary value is freed at the end of this statement
   |                |
   |                creates a temporary value which is freed while still in use
32 |     println!("{}", path.display());
   |                    ---- borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value
runic creek
#

You need to keep the temporary that's created by entry.path() in scope while you are borrowing from it

Can do that by using another let binding

let path = entry.path();
let path = path.as_ref();

Should work, if it complains still then the second let should have a different name

fervent hinge
#

is there a way to do it inline?

runic creek
#

Nah, borrowing in rust requires that the value it's borrowing from has storage, which the let bindings do for you. Sometimes rust can do lifetime extension for you but not in all cases

fervent hinge
#

so there is no way to do inline temp or smth?

fervent hinge
#

never mind.

#

for some reason, replacing the Error part of the returned result type to a () it breaks the ? which makes sense.
but it makes it so you can have entry?.path().as_path(). but to fix the ? you add it back to Error which breaks the inline.

runic creek
#

That just sounds like trading one compiler error for another tbh 😄

fervent hinge
#

but thr error result should have nothing to do with the borrow

#

also, do you know of a good markdown to js html node parser?

runic creek
# fervent hinge but thr error result should have nothing to do with the borrow

Yeah, but I believe the borrow checker pass runs after the compiler typechecking pass....at least I believe I've seen it before where I have a bunch of errors, fix those, then get a bunch more

In your case if the type of the error is wrong you won't see the lifetime compile errors until it's fixed because it fails before that pass