1

After grabbing the file path of the executable and appending nvs on it in inner_main(), I try to convert it to a string in main():

use std::{env, io, path::PathBuf, process};

fn inner_main() -> io::Result<PathBuf> {
    let exe = env::current_exe()?;
    let dir = exe.parent().expect("Executable must be in some directory");
    let dir = dir.join("nvs");
    Ok(dir)
}

fn main() {
    let path = inner_main() as String;
    println!("The current directory is {:?}", path);
    process::exit(0);
}

It results in an error:

error[E0605]: non-primitive cast: `std::result::Result<std::path::PathBuf, std::io::Error>` as `std::string::String`
  --> src/main.rs:11:16
   |
11 |     let path = inner_main() as String;
   |                ^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

How would I go about converting this to a String or &str?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
SmushyTaco
  • 1,421
  • 2
  • 16
  • 32
  • Have you tried `path.to_str().expect("Invalid path")`? It's listed in the [docs](https://doc.rust-lang.org/std/path/struct.PathBuf.html). – grooveplex Jul 05 '19 at 00:24
  • @grooveplex no method named `to_str` found for type std:: `result::Result` in current scope – SmushyTaco Jul 05 '19 at 00:32
  • `path.expect("Need a path").to_str().expect("Path contains invalid UTF-8");` – Thomas Hurst Jul 05 '19 at 00:55
  • But really, you want `println!(".. {}", path.expect("need a path").display());` - keep it as a PathBuf where possible, use the Display trait to (potentially lossily) render it. – Thomas Hurst Jul 05 '19 at 00:56

2 Answers2

3

If you are just printing the path, you can use PathBuf::display

let path = inner_main().unwrap();
println!("The current directory is {}", path.display());

If you need a string, you could use:

let path: String = inner_main().unwrap().to_str().unwrap().to_string();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Manu
  • 76
  • 1
  • 4
1

Quick rework:

use std::path::PathBuf;
use std::process;
use std::env;
use std::io;

fn inner_main() -> io::Result<PathBuf> {
    let mut exe = env::current_exe()?;
    exe.set_file_name("nvs");
    Ok(exe)
}

fn main() {
    match inner_main() {
        Ok(path) => println!("The current directory is {}", path.display()),
        Err(e) => {
            eprintln!("Error determining executable path: {}", e);
            process::exit(1);
        }
    }
}

I think PathBuf.set_file_name() has the semantics you're aiming for, and is helpfully infallible.

PathBuf.display() returns an object implementing the Display trait, which is used for user-facing formatting. It should be noted that this will lossily convert to UTF-8 - paths should remain as PathBuf for any filesystem operations you're performing.

Thomas Hurst
  • 124
  • 2
  • 4