Я пытаюсь реализовать механизм нулевого копирования для обработки данных в реальном времени в Rust. Чтобы проиллюстрировать мою проблему, я подготовил следующий пример:
use std::io;
pub trait Producer<T> {
fn produce(&self) -> Result<T, ()>;
}
pub trait Consumer<T> {
fn consume(&self, t: T);
}
pub trait Source<T> : Producer<T> {
fn push(&self, t: T) -> io::Result<()>;
}
pub trait Sink<T> : Consumer<T> {
fn pull(&self) -> io::Result<T>;
}
pub struct SyncSource<T> {
pub producer: Option<Box<dyn Fn() -> T>>,
}
impl<T> SyncSource<T> {
pub fn new() -> SyncSource<T> {
SyncSource {
producer: None,
}
}
}
impl<T> Producer<T> for SyncSource<T> {
fn produce(&self) -> Result<T, ()> {
match &self.producer {
Some(func) => Ok((*(func))()),
None => Err(()),
}
}
}
impl<T> Source<T> for SyncSource<T> {
fn push(&self, t: T) -> io::Result<()> {
// do something useful
Ok(())
}
}
pub struct Frame<'a> {
pub buf: &'a [u8],
}
pub struct Capture {
buf: Vec<u8>,
}
impl Capture {
pub fn add(&mut self, val: u8) {
self.buf.push(val);
}
pub fn read(&self) -> Frame {
Frame {
buf: &self.buf[..],
}
}
}
fn main() {
let mut capture = Capture {
buf: Vec::new(),
};
let source: SyncSource<Frame> = SyncSource::new();
// immutable borrow of 'capture'
let frame = capture.read();
source.push(frame);
// mutable borrow of 'capture'
capture.add(1); // ERROR
}
.., что, конечно, приводит к ошибке проверки заимствования:
error[E0502]: cannot borrow `capture` as mutable because it is also borrowed as immutable
--> src/bin/so.rs:212:5
|
208 | let frame = capture.read();
| ------- immutable borrow occurs here
...
212 | capture.add(1);
| ^^^^^^^^^^^^^^ mutable borrow occurs here
213 | }
| - immutable borrow might be used here, when `source` is dropped and runs the destructor for type `SyncSource<'_, Frame<'_>>`
Я понимаю, что push(frame)
не может иметь неизменяемый ссылка в той же области, где capture.add(1)
нужна изменяемая ссылка через несколько строк.
Я пытаюсь добиться, чтобы push(frame)
смог сделать что-то полезное со слайсом (и, возможно, скопировать это в Ve c при необходимости), но с возможностью ничего с ним не делать.
По сути, мне нужно убедиться, что время жизни frame
заканчивается после вызова push(frame)
. Это затем освободит заимствованную ссылку на Capture
, и вызов capture.add(1)
завершится успешно, когда будет получена правильная изменяемая ссылка.
Мое требование нулевой копии предписывает не копировать фрагмент в Ve c и затем передать этот новый буфер в push(..)
. Что мне здесь не хватает? Возможно, какие-то явные аннотации времени жизни?