在将PathBuf转换为String时,有没有办法避免克隆?

时间:2017-01-23 15:30:14

标签: string rust std ownership-semantics

我需要简单地(并且危险地 - 为了简洁省略了错误处理)获取当前的可执行文件名。我已将其设为有效,但我的功能仅将&str转换为String,以便稍后调用as_str()进行模式匹配。

fn binary_name() -> String {
    std::env::current_exe().unwrap().file_name().unwrap().to_str().unwrap().to_string()
}

根据我的理解,std::env::current_exe()授予我PathBuf的所有权,我可以通过寄回来转让。{1}}按照目前的情况,我借用它将其转换为&str。从那里,返回字符串的唯一方法是在删除PathBuf之前克隆它。

有没有办法避免这个&OsStr -> &str -> String -> &str周期?

1 个答案:

答案 0 :(得分:3)

  

PathBuf转换为String时,有没有办法避免克隆?

绝对。但是,这不是你在做什么。您正在通过PathBuffile_name进行部分并进行转换。你不能取得一部分字符串的所有权。

如果您没有拍摄子集,则可以转换为PathBuf然后转换为OsString来转换整个String。在这里,我忽略了具体的错误,只是返回成功或失败:

use std::path::PathBuf;

fn exe_name() -> Option<String> {
    std::env::current_exe()
        .ok()
        .map(PathBuf::into_os_string)
        .and_then(|exe| exe.into_string().ok())
}
  

有没有办法避免这个&OsStr -> &str -> String -> &str周期?

不,因为您在方法中创建了String(或OsStringPathBuf,取决于代码的变体,取决于代码的变体。查看Return local String as a slice (&str),了解为什么不能返回对堆栈分配项(包括字符串)的引用。

如Q&amp; A所述,如果您想要引用,拥有数据的东西必须比引用更长:

use std::env;
use std::path::Path;
use std::ffi::OsStr;

fn binary_name(path: &Path) -> Option<&str> {
    path.file_name().and_then(OsStr::to_str)
}

fn main() {
    let exe = env::current_exe().ok();
    match exe.as_ref().and_then(|e| binary_name(e)) {
        Some("cat") => println!("Called as cat"),
        Some("dog") => println!("Called as dog"),
        Some(other) => println!("Why did you call me {}?", other),
        None => println!("Not able to figure out what I was called as"),
    }
}

您的原始代码可以编写为不会轻易导致错误崩溃

fn binary_name() -> Option<String> {
    let exe = std::env::current_exe();
    exe.ok()
        .as_ref()
        .and_then(|p| p.file_name())
        .and_then(|s| s.to_str())
        .map(String::from)
}