问题描述
我正在尝试实现一个通用结构,从一开始就很清楚它的元素 'provider' 必须是稍后支持 &myvar.provider[..] 的类型。但我无法为此找到正确的 Bound。
pub struct MyStruct<T: ??> { // T must support &x.provider[..]
pub provider: T,}
非常感谢您的帮助
更新:扩展示例。我想要实现的是:数据块可以达到 10GB。它们可以作为静态 b"aa" 提供,主要用于测试、将文件内容读入内存或映射文件内容。无论提供者如何,在处理数据时我们只使用 &[u8]。
//
// A minimal example for my problem
//
use std::str;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::Boxed::Box;
use memmap::{MmapOptions,Mmap};
#[derive(Debug)]
pub struct DBFileBuilder<T> { // what is the correct bound? T must support &x[..]
pub filename: String,pub provider: Option<T>,pub startpos: usize,// ... several more
}
pub struct DBFile<'a,T> { // what is the correct bound? T must support &x[..]
pub filename: String,pub provider: T,pub data: &'a [u8],// ... several more
}
impl<T> DBFileBuilder<T> {
fn default() -> Self {
Self {
filename: String::default(),provider: None,startpos: 0,}
}
pub fn from_bytes(data: &[u8]) -> DBFileBuilder<&[u8]> {
DBFileBuilder {
provider: Some(&data),..DBFileBuilder::default()
}
}
pub fn read_file(filename: &str) -> Result<DBFileBuilder<Box<[u8]>>,Box<dyn Error>> {
let mut file = File::open(&filename)?;
let fsize = file.Metadata()?.len();
let mut provider = vec![0_u8; fsize as usize].into_Boxed_slice();
let n = file.read(&mut provider)?;
Ok(DBFileBuilder {
filename: filename.to_string(),provider: Some(provider),..DBFileBuilder::default()
})
}
pub fn mmap_file(filename: &str) -> Result<DBFileBuilder<Mmap>,Box<dyn Error>> {
let file = File::open(&filename)?;
let provider = unsafe { MmapOptions::new().map(&file)? };
Ok(DBFileBuilder {
filename: filename.to_string(),..DBFileBuilder::default()
})
}
pub fn init(&mut self) {
}
pub fn build<'a>(self) -> DBFile<'a,T> {
let provider = self.provider.expect("Provider not initialized");
self.init();
let data = &provider[self.startpos ..];
DBFile {
filename: self.filename,provider,data,}
}
}
impl<'a,T> DBFile<'a,T> {
pub fn run(&self) {
return self.process(self.data)
}
pub fn process(&self,data: &[u8]) {
println!("data: {:?}",&data);
}
}
解决方法
通过使用封闭范围来获取字节绑定到索引的必要特征是Index<Range<usize>,Output=[u8]>
。
您可能还想按无限范围索引:
pub struct MyStruct<T>
where T: Index<Range<usize>,Output=[u8]>
+ Index<RangeTo<usize>,Output=[u8]>
+ Index<RangeFrom<usize>,Output=[u8]>
+ Index<RangeFull,Output=[u8]>
{
pub provider: T,}
不幸的是,目前在使用 MyStruct
的签名中没有推断出这些边界(尽管我相信这是在进行中),这会变得非常笨拙。如果您使用 Nightly,您可以定义一个 trait alias (RFC1733) 以减少冗长。
也就是说,您需要重新考虑示例,因为它不起作用:例如在 build()
中,data
不能成为返回的 DBFile
的一部分,因为它指向一个存活时间不够长的局部变量。