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}