Есть ли способ избежать клонирования при преобразовании PathBuf в строку?
Мне нужно просто (и опасно - обработка ошибок опущена для краткости) получить текущее имя исполняемого файла. Я сделал это работает, но моя функция преобразует &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
который я мог бы передать, вернув его. В настоящее время я одалживаю его, чтобы преобразовать в &str
, Оттуда единственный способ вернуть строку - это клонировать ее до PathBuf
упал
Есть ли способ избежать этого &OsStr -> &str -> String -> &str
цикл?
1 ответ
Есть ли способ избежать клонирования при конвертации
PathBuf
кString
?
Абсолютно. Однако это не то, что вы делаете. Вы принимаете участие в PathBuf
с помощью file_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
(или же OsString
или же PathBuf
в зависимости от варианта кода) внутри вашего метода. Проверьте возврат локальной строки в качестве среза (&str), почему вы не можете вернуть ссылку на выделенный стеком элемент (включая строку).
Как указано в этом разделе "Вопросы и ответы", если вы хотите иметь ссылки, то вещь, владеющая данными, должна пережить ссылки:
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)
}