buffed/
guard.rs

1//! Guards provided to help implementations of
2//! [`BuffedRead`][crate::BuffedRead] avoid Undefined Behavior.
3use core::marker::PhantomData;
4
5use crate::buffer::Buffer;
6
7/// A guard that will discard a [`BuffedRead`][crate::BuffedRead]'s internal
8/// buffer.
9///
10/// It can be used to ensure that invalid state cannot be observed when the
11/// reader's state is temporarily made invalid. This is needed because if
12/// the code panics before a valid state is restored, this invalid state may
13/// be then observed and trigger Undefined Behavior.
14///
15// TODO: Add an example
16#[derive(Debug)]
17pub struct DiscardOnDrop<'r, T, A = alloc::alloc::Global>
18where
19    T: Buffer<A>,
20    A: alloc::alloc::Allocator + Default,
21{
22    /// The guarded reader.
23    pub buf: &'r mut T,
24    _alloc: PhantomData<A>,
25}
26
27impl<'r, T, A> core::ops::Deref for DiscardOnDrop<'r, T, A>
28where
29    T: Buffer<A>,
30    A: alloc::alloc::Allocator + Default,
31{
32    type Target = T;
33
34    fn deref(&self) -> &Self::Target {
35        self.buf
36    }
37}
38
39impl<'r, T, A> core::ops::DerefMut for DiscardOnDrop<'r, T, A>
40where
41    T: Buffer<A>,
42    A: alloc::alloc::Allocator + Default,
43{
44    fn deref_mut(&mut self) -> &mut Self::Target {
45        self.buf
46    }
47}
48
49impl<T, A> Drop for DiscardOnDrop<'_, T, A>
50where
51    T: Buffer<A>,
52    A: alloc::alloc::Allocator + Default,
53{
54    fn drop(&mut self) {
55        self.buf.discard();
56    }
57}
58
59impl<'r, T, A> DiscardOnDrop<'r, T, A>
60where
61    T: Buffer<A>,
62    A: alloc::alloc::Allocator + Default,
63{
64    pub fn new(reader: &'r mut T) -> Self {
65        DiscardOnDrop {
66            buf: reader,
67            _alloc: PhantomData,
68        }
69    }
70}