gpt4 book ai didi

rust - 从字符串的随机 Vec 读取文件

转载 作者:行者123 更新时间:2023-12-04 07:17:08 24 4
gpt4 key购买 nike

我想从 Vec<String> 随机读取一个文件然后将其用作 reqwest async 的多部分
但我不断得到:
borrowed value doesn't live long enough
这是功能

fn getFiles(dirname: &str) -> Vec<String> {
let mut items: Vec<String> = Vec::new();
let dir = std::fs::read_dir(dirname);
for item in dir.expect("fail") {
if let Ok(item) = item {
items.push(item.path().into_os_string().into_string().unwrap());
}
}
items
}
// call the function
let dir_items = getFiles("src/assets");
let file = dir_items.into_iter().choose(&mut rand::thread_rng()).unwrap();
let path = std::path::Path::new(&file);
let sub_file = std::fs::read(path)?;
// after this, file lifetime is already end ?
let sub_file_part = reqwest::multipart::Part::bytes(sub_file)
.file_name(path.file_name().unwrap().to_string_lossy())
.mime_str("application/octet-stream")?;
playground

最佳答案

让我们逐个看一下:

let path = std::path::Path::new(&file);
如果你看看 the documentation for Path::new ,您会看到以下签名:
pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path
应用第二个 lifetime elision rules 后,(引用:“如果只有一个输入生命周期参数,则该生命周期将分配给所有输出生命周期参数: fn foo<'a>(x: &'a i32) -> &'a i32”),此签名实际上如下所示:
pub fn new<'a, S: AsRef<OsStr> + ?Sized>(s: &'a S) -> &'a Path
所以,你的 path变量的生命周期不能超过你的 file多变的。
接下来,这是相关的:
.file_name(path.file_name().unwrap().to_string_lossy())
再次应用生命周期省略规则后,您可以看到调用 unwrap path.file_name() 给你一个 &std::ffi::OsStr 生命周期不能超过你的 path反过来(如前所述)的变量不能比你的 file多变的。所以,传递地, path.filename().unwrap()活不过 file多变的。
现在,让我们看一下 OsStr::to_string_lossy() 的签名。 :
pub fn to_string_lossy(&self) -> Cow<'_, str>
因此,此方法返回 Cow<'_, str> . Cow是“复制或拥有”的简写——意味着 Cow可以包含对数据的引用(在本例中为 &str ,如果 OsStr 仅包含有效的 UTF-8 字节),或者它可以拥有数据本身(在本例中,通过包含 String ,如果 OsStr 包含需要在 UTF-8 转换期间转换或过滤掉的数据)。 '_ is a placeholder and means that the compiler shall (again) infer the lifetime with the lifetime elision rules .扩展签名如下所示:
pub fn to_string_lossy<'a>(&'a self) -> Cow<'a, str>
因此,在您的示例中, 'a不能大于 &OsStr 的生命周期由 unwrap() 返回,这意味着 'a不能大于 file 的生命周期.
但是, reqwest::multipart::Part::file_name() 期望实现 Into<Cow<'static, str>>作为参数。我们的 Cow<'a, str>绝对无法实现,因为我们的 file变量在程序结束之前是不活跃的。如果它在程序结束之前还活着,我们的 Cow会实现它,因为 file可借 'static ,一切都会好起来的——这就是错误消息的原因。
您可以调用 into_owned() 来解决此问题。在 Cow .这将转换 Cow成一个字符串,它确实实现了 Into<Cow<'static, str>> :
use rand::prelude::*;

fn getFiles(dirname: &str) -> Vec<String> {
let mut items: Vec<String> = Vec::new();
let dir = std::fs::read_dir(dirname);
for item in dir.expect("fail") {
if let Ok(item) = item {
items.push(item.path().into_os_string().into_string().unwrap());
}
}
items
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
// call the function
let dir_items = getFiles("src/assets");
let file = dir_items.into_iter().choose(&mut rand::thread_rng()).unwrap();
let path = std::path::Path::new(&file);
let sub_file = std::fs::read(path)?;
// after this, file lifetime is already end ?
let sub_file_part = reqwest::multipart::Part::bytes(sub_file)
.file_name(path.file_name().unwrap().to_string_lossy().into_owned())
.mime_str("application/octet-stream")?;
Ok(())
}
Playground

关于rust - 从字符串的随机 Vec 读取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68698767/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com