1 个稳定版本
新版本 1.0.0 | 2024 年 8 月 16 日 |
---|
770 在 Rust 模式 中
29KB
451 行
loopcell
专为读-改-写风格的循环设计的 cell 类型,避免手动写入步骤。
在具有多个输入流复杂事件处理服务中很有用,特别是当你在下一次迭代之前丢弃产生的值时,它非常适合迭代器范式。在许多方面,它可以作为一个“运行时版本”的借用迭代器。
它还与 qcell
、ghost_cell
和类似包很好地结合使用,如果你使用 LoopCell
或 LoopSyncCell
作为所有权控制类型。
快速示例
这是一个快速示例,说明了如何使用 LoopCell
创建一个迭代器,该迭代器重用共享缓冲区以处理事件。您可以使用 LoopSyncCell
做到类似的事情,但在需要跨线程转移访问的情况下(在实现 futures 时很常见),它将工作得更好。
use std::ops::{Deref, DerefMut};
pub struct Event {
/// If `true`, then no more events should be processed after this.
pub last: bool
}
impl Event {
/// Dummy function that writes to the buffer.
pub fn serialize_into(self, buffer: &mut Vec<u8>) {
buffer.extend(b"DUMMY VALUE\n");
}
}
/// This illustrates the way this can be used as a pseudo-runtime-lending-iterator.
/// While this specific case could be implemented without the loopcell, in more complex
/// cases like having multiple iterators that all reuse the buffer or provide values that
/// reference the buffer, this is not possible because only one would be able to hold a
/// mutable reference at a time
fn write_events(events: impl Iterator<Item = Event>, mut process_event_bytes: impl FnMut(&mut [u8])) {
let buffer = loopcell::LoopCell::new(Vec::<u8>::with_capacity(8192));
// Iterator that returns `Some` of an access to the buffer, while it's refilled.
let buffer_iter = core::iter::from_fn(|| buffer.access()).fuse();
for (mut buffer_handle, next_event) in buffer_iter.zip(events) {
let is_last_event = next_event.last;
{
let mut buffer_access = WipeOnDrop::from(buffer_handle.as_mut());
next_event.serialize_into(&mut buffer_access);
process_event_bytes(&mut buffer_access);
}
if is_last_event {
buffer_handle.consume();
}
}
}
fn main() {
// Illustrate the way the loopcell enables iteration using conditional consumption of
// the handles.
let mut counter = 0;
let mut increment_counter = |_bytes: &mut _| { counter += 1; };
let events = [false, false, false, true].map(|last| Event { last });
write_events(events.into_iter(), &mut increment_counter);
assert_eq!(counter, 4);
}
/// Implementation detail that wipes a buffer with `clear()` on drop, but inherently preserves capacity.
pub struct WipeOnDrop<'b>(&'b mut Vec<u8>);
impl <'b> From<&'b mut Vec<u8>> for WipeOnDrop<'b> {
fn from(v: &'b mut Vec<u8>) -> Self {
Self(v)
}
}
impl <'b> Deref for WipeOnDrop<'b> {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl <'b> DerefMut for WipeOnDrop<'b> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl <'b> Drop for WipeOnDrop<'b> {
fn drop(&mut self) {
self.0.clear()
}
}
依赖项
~33KB