diff options
author | Vincent Ambo <mail@tazj.in> | 2024-10-12T22·40+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2024-10-12T23·02+0000 |
commit | bd8d6e824f0bfc3c2755713af36f815d0ee82edb (patch) | |
tree | cf1b64998e2d199442bedfb25a85806e8b4e89ba /users/edef/turbofetch/src/buffer.rs | |
parent | 398a9b531758297417280ccf06b82c85f3d236dd (diff) |
chore(tvix/tools): move turbofetch to //users/edef r/8799
This was introduced in cl/9925 without any commit message, but this is clearly not relevant to Tvix itself (it even says so in a comment in Cargo.toml). Change-Id: I84f12d5145c3f53c9df23863f887bad913856c50 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12604 Tested-by: BuildkiteCI Autosubmit: tazjin <tazjin@tvl.su> Reviewed-by: edef <edef@edef.eu>
Diffstat (limited to 'users/edef/turbofetch/src/buffer.rs')
-rw-r--r-- | users/edef/turbofetch/src/buffer.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/users/edef/turbofetch/src/buffer.rs b/users/edef/turbofetch/src/buffer.rs new file mode 100644 index 000000000000..d6ff93e3cfe7 --- /dev/null +++ b/users/edef/turbofetch/src/buffer.rs @@ -0,0 +1,83 @@ +use magic_buffer::MagicBuffer; +use std::cell::Cell; + +/// Buffer is a FIFO queue for bytes, built on a ring buffer. +/// It always provides contiguous slices for both the readable and writable parts, +/// using an underlying buffer that is "mirrored" in virtual memory. +pub struct Buffer { + buffer: MagicBuffer, + /// first readable byte + head: Cell<usize>, + /// first writable byte + tail: usize, +} + +impl Buffer { + /// Allocate a fresh buffer, with the specified capacity. + /// The buffer can contain at most `capacity - 1` bytes. + /// The capacity must be a power of two, and at least [Buffer::min_len]. + pub fn new(capacity: usize) -> Buffer { + Buffer { + // MagicBuffer::new verifies that `capacity` is a power of two, + // and at least MagicBuffer::min_len(). + buffer: MagicBuffer::new(capacity).unwrap(), + // `head == tail` means the buffer is empty. + // In order to ensure that this remains unambiguous, + // the buffer can only be filled with capacity-1 bytes. + head: Cell::new(0), + tail: 0, + } + } + + /// Returns the minimum buffer capacity. + /// This depends on the operating system and architecture. + pub fn min_capacity() -> usize { + MagicBuffer::min_len() + } + + /// Return the capacity of the buffer. + /// This is equal to `self.data().len() + self.space().len() + 1`. + pub fn capacity(&self) -> usize { + self.buffer.len() + } + + /// Return the valid, readable data in the buffer. + pub fn data(&self) -> &[u8] { + let len = self.buffer.len(); + let head = self.head.get(); + + if head <= self.tail { + &self.buffer[head..self.tail] + } else { + &self.buffer[head..self.tail + len] + } + } + + /// Mark `read_len` bytes of the readable data as consumed, freeing the space. + pub fn consume(&self, read_len: usize) { + debug_assert!(read_len <= self.data().len()); + let mut head = self.head.get(); + head += read_len; + head &= self.buffer.len() - 1; + self.head.set(head); + } + + /// Return the empty, writable space in the buffer. + pub fn space(&mut self) -> &mut [u8] { + let len = self.buffer.len(); + let head = self.head.get(); + + if head <= self.tail { + &mut self.buffer[self.tail..head + len - 1] + } else { + &mut self.buffer[self.tail..head - 1] + } + } + + /// Mark `written_len` bytes of the writable space as valid, readable data. + pub fn commit(&mut self, written_len: usize) { + debug_assert!(written_len <= self.space().len()); + self.tail += written_len; + self.tail &= self.buffer.len() - 1; + } +} |