特征对象,并将 n 个字节读入向量
Trait objects, and reading n bytes into vector
假设我有以下内容,
use std::io;
use std::io::Read;
#[derive(Debug)]
enum FooReadError {
UnexpectedEof,
IoError(io::Error),
}
impl From<io::Error> for FooReadError {
fn from(err: io::Error) -> FooReadError {
FooReadError::IoError(err)
}
}
fn read_n_bytes_to_vector<R: Read>(reader: &mut R, length: usize)
-> Result<Vec<u8>, FooReadError> {
let mut bytes = Vec::<u8>::with_capacity(length);
unsafe { bytes.set_len(length); }
let bytes_read = try!(reader.read(&mut bytes[..]));
if bytes_read != length {
Err(FooReadError::UnexpectedEof)
} else {
Ok(bytes)
}
}
fn do_some_read(reader: &mut Read) -> Vec<u8> {
read_n_bytes_to_vector(reader, 16).unwrap()
}
fn main() {
let v = vec![0, 1, 2, 3, 4, 5];
let mut cur = io::Cursor::<Vec<u8>>::new(v);
do_some_read(&mut cur);
}
read_n_bytes_to_vector
应该采用任何实现特征 io::Read
的东西,从中读取 length
字节,并将它们放入向量和 return 向量中。
函数 do_some_read
有一个 io::Read
特征 对象。那么,为什么:
% rustc ./vec_read.rs
./vec_read.rs:29:5: 29:27 error: the trait `core::marker::Sized` is not implemented for the type `std::io::Read` [E0277]
./vec_read.rs:29 read_n_bytes_to_vector(reader, 16).unwrap()
^~~~~~~~~~~~~~~~~~~~~~
./vec_read.rs:29:5: 29:27 note: `std::io::Read` does not have a constant size known at compile-time
./vec_read.rs:29 read_n_bytes_to_vector(reader, 16).unwrap()
^~~~~~~~~~~~~~~~~~~~~~
我同意编译器 io::Read
不可能实现 Sized
;但是我传递了一个特征 object — 它们是恒定大小的,所以在这里应该没问题; **那么为什么会出现错误?* 但是等等,为什么这很重要?该函数没有将 io::Read
作为 arg( 对吗?),它也采用了特征对象,因为 arg 是通用的,应该采用完整类型传入了什么。
泛型默认包含 Sized
绑定;如果您不希望它被要求,您必须添加 ?Sized
绑定。
特征对象不是大小不变; u16 as Trait
是两个字节,u32 as Trait
是四个字节,&c.;只有 boxed 特征对象 (Box<Trait>
) 和特征对象 references (&Trait
, &mut Trait
)有一个恒定的大小,在编译时已知(引用示例的两个词)。
因为你只通过可变引用使用了一个R
,你可以成功添加?Sized
绑定:
fn read_n_bytes_to_vector<R: ?Sized + Read>(reader: &mut R, length: usize)
-> Result<Vec<u8>, FooReadError> {
假设我有以下内容,
use std::io;
use std::io::Read;
#[derive(Debug)]
enum FooReadError {
UnexpectedEof,
IoError(io::Error),
}
impl From<io::Error> for FooReadError {
fn from(err: io::Error) -> FooReadError {
FooReadError::IoError(err)
}
}
fn read_n_bytes_to_vector<R: Read>(reader: &mut R, length: usize)
-> Result<Vec<u8>, FooReadError> {
let mut bytes = Vec::<u8>::with_capacity(length);
unsafe { bytes.set_len(length); }
let bytes_read = try!(reader.read(&mut bytes[..]));
if bytes_read != length {
Err(FooReadError::UnexpectedEof)
} else {
Ok(bytes)
}
}
fn do_some_read(reader: &mut Read) -> Vec<u8> {
read_n_bytes_to_vector(reader, 16).unwrap()
}
fn main() {
let v = vec![0, 1, 2, 3, 4, 5];
let mut cur = io::Cursor::<Vec<u8>>::new(v);
do_some_read(&mut cur);
}
read_n_bytes_to_vector
应该采用任何实现特征 io::Read
的东西,从中读取 length
字节,并将它们放入向量和 return 向量中。
函数 do_some_read
有一个 io::Read
特征 对象。那么,为什么:
% rustc ./vec_read.rs
./vec_read.rs:29:5: 29:27 error: the trait `core::marker::Sized` is not implemented for the type `std::io::Read` [E0277]
./vec_read.rs:29 read_n_bytes_to_vector(reader, 16).unwrap()
^~~~~~~~~~~~~~~~~~~~~~
./vec_read.rs:29:5: 29:27 note: `std::io::Read` does not have a constant size known at compile-time
./vec_read.rs:29 read_n_bytes_to_vector(reader, 16).unwrap()
^~~~~~~~~~~~~~~~~~~~~~
我同意编译器 io::Read
不可能实现 Sized
;但是我传递了一个特征 object — 它们是恒定大小的,所以在这里应该没问题; **那么为什么会出现错误?* 但是等等,为什么这很重要?该函数没有将 io::Read
作为 arg( 对吗?),它也采用了特征对象,因为 arg 是通用的,应该采用完整类型传入了什么。
泛型默认包含 Sized
绑定;如果您不希望它被要求,您必须添加 ?Sized
绑定。
特征对象不是大小不变; u16 as Trait
是两个字节,u32 as Trait
是四个字节,&c.;只有 boxed 特征对象 (Box<Trait>
) 和特征对象 references (&Trait
, &mut Trait
)有一个恒定的大小,在编译时已知(引用示例的两个词)。
因为你只通过可变引用使用了一个R
,你可以成功添加?Sized
绑定:
fn read_n_bytes_to_vector<R: ?Sized + Read>(reader: &mut R, length: usize)
-> Result<Vec<u8>, FooReadError> {