我需要构造一个类型,可以从库中传递给以下函数。
pub fn read_write_pair<R, W>(read: R, write: W) -> Term
where
R: BufRead + Debug + Send + 'static,
W: Write + AsRawFd + Debug + Send + 'static,
{
// details elided...
}
此外,我希望能够为我的测试操作read
和write
。具体来说,我希望能够在没有任何内容的情况下构建这两个实例,将它们传递给这个函数,然后用字母设置库将读取的内容并提取它所写的内容。
这就是我对将用于read
侧的Input
类型的了解:
#[derive(Debug)]
pub struct Input {
prepared_content: Arc<Mutex<Cursor<Vec<u8>>>>,
}
impl Clone for Input {
fn clone(&self) -> Self {
Self {
prepared_content: Arc::clone(&self.prepared_content),
}
}
}
impl Input {
fn new() -> Self {
Self {
prepared_content: Default::default(),
}
}
fn append(&mut self, content: &str) {
let mut cursor = self.prepared_content.lock().unwrap();
cursor.get_mut().extend_from_slice(content.as_bytes());
}
}
impl Read for Input {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.prepared_content.lock().unwrap().read(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
self.prepared_content.lock().unwrap().read_exact(buf)
}
}
impl BufRead for Input {
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
let mut content = self.prepared_content.lock().unwrap();
content.fill_buf()
}
fn consume(&mut self, amt: usize) {
self.prepared_content.lock().unwrap().consume(amt)
}
}
由内而外:
Vec<u8>
是要读取的内容Cursor
使其成为BufRead
- 当我想添加更多要读取的内容时,
Mutex
允许内部可变。它还使类型Send
和Sync
Arc
让我拥有多个所有者——我的测试函数和库本身
问题来自BufRead
的fill_buff
:它返回的Result<&[u8]>
将比MutexGuard本身更长。Cell
会给我同样的内部可变性,但它不是发送/同步,我怀疑Cursor
是复制。
我还有其他策略可以尝试吗?
从根本上讲,不可能将&[u8]
获取到共享的内部可变缓冲区,因为这将允许在存在不可变引用的情况下进行突变。(作为这个规则边界上的一个例子:Cell::get_mut
允许获得引用,但需要&mut
到Cell,从而确保Cell当前不共享。(
想到的一件简单的事情是,传递一个BufReader<Input>
,而不是为Input
实现BufRead
。然后,您仍然可以从外部提供要读取的字节,但不负责缓冲区。然而,这可能读得太多了。如果这对您不起作用,您将不得不使用内部不可变的缓冲区来实现BufRead
,也就是
#[derive(Debug)]
pub struct Input {
prepared_content: Arc<Mutex<Cursor<Vec<u8>>>>,
buffer: Vec<u8>,
}
并且该实现根据需要将字节从CCD_ 24传输到CCD_。
这种方法意味着您不能从测试代码中交换出缓冲区的内容,但也不应该这样做,因为这违反了BufRead
实现将保持其所提供的缓冲字节不变的合理预期,直到调用方处理完它们(通过调用consume()
(。