bytesbuf/
memory_guard.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use smallvec::SmallVec;
5
6use crate::{BlockRef, MAX_INLINE_SPANS};
7
8/// Guards memory blocks with a liveness lock, preventing a set of memory blocks
9/// from being released while the guard is alive.
10///
11/// Call [`BytesView::extend_lifetime()`][1] or [`BytesBuf::extend_lifetime()`][2] to obtain
12/// an instance.
13///
14/// The memory may be used for any otherwise legal purpose; all this guard does is act as a
15/// shadow reference to the memory blocks. This can be useful when executing unsafe logic,
16/// where there may not otherwise exist any Rust objects holding references to memory blocks
17/// in use (e.g. because the code operating on them is not even Rust code).
18///
19/// [1]: crate::BytesView::extend_lifetime
20/// [2]: crate::BytesBuf::extend_lifetime
21#[derive(Debug)]
22#[must_use]
23pub struct MemoryGuard {
24    _block_refs: SmallVec<[BlockRef; MAX_INLINE_SPANS]>,
25}
26
27impl MemoryGuard {
28    /// Creates a new memory guard for the provided memory blocks.
29    pub(crate) fn new(block_refs: impl IntoIterator<Item = BlockRef>) -> Self {
30        Self {
31            _block_refs: block_refs.into_iter().collect(),
32        }
33    }
34}
35
36impl Default for MemoryGuard {
37    /// Creates a memory guard that does not guard any memory blocks.
38    ///
39    /// Useless for real logic but potentially meaningful as a placeholder in tests.
40    fn default() -> Self {
41        Self::new(vec![])
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[expect(clippy::used_underscore_binding, reason = "Sometimes, you gotta do what you gotta do.")]
50    #[test]
51    fn default_creates_empty_guard() {
52        let guard = MemoryGuard::default();
53        assert!(guard._block_refs.is_empty());
54    }
55}