1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use super::{utils::modulus, Based};
use core::{mem::MaybeUninit, num::NonZeroUsize};

/// Ring buffer observer.
///
/// Can observe ring buffer state but cannot safely access its data.
pub trait Observer {
    type Item: Sized;

    /// Capacity of the ring buffer.
    ///
    /// It is constant during the whole ring buffer lifetime.
    fn capacity(&self) -> NonZeroUsize;

    /// Index of the last item in the ring buffer.
    ///
    /// Index value is in range `0..(2 * capacity)`.
    fn read_index(&self) -> usize;
    /// Index of the next empty slot in the ring buffer.
    ///
    /// Index value is in range `0..(2 * capacity)`.
    fn write_index(&self) -> usize;

    /// Get slice between `start` and `end` indices.
    ///
    /// # Safety
    ///
    /// Slice must not overlap with any mutable slice existing at the same time.
    ///
    /// Non-`Sync` items must not be accessed from multiple threads at the same time.
    unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]);

    /// Get mutable slice between `start` and `end` indices.
    ///
    /// # Safety
    ///
    /// There must not exist overlapping slices at the same time.
    unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]);

    /// Whether read end is held by consumer.
    fn read_is_held(&self) -> bool;
    /// Whether write end is held by producer.
    fn write_is_held(&self) -> bool;

    /// The number of items stored in the buffer.
    ///
    /// *Actual number may be greater or less than returned value due to concurring activity of producer or consumer respectively.*
    fn occupied_len(&self) -> usize {
        let modulus = modulus(self);
        (modulus.get() + self.write_index() - self.read_index()) % modulus
    }

    /// The number of remaining free places in the buffer.
    ///
    /// *Actual number may be greater or less than returned value due to concurring activity of consumer or producer respectively.*
    fn vacant_len(&self) -> usize {
        let modulus = modulus(self);
        (self.capacity().get() + self.read_index() - self.write_index()) % modulus
    }

    /// Checks if the ring buffer is empty.
    ///
    /// *The result may become irrelevant at any time because of concurring producer activity.*
    #[inline]
    fn is_empty(&self) -> bool {
        self.read_index() == self.write_index()
    }

    /// Checks if the ring buffer is full.
    ///
    /// *The result may become irrelevant at any time because of concurring consumer activity.*
    #[inline]
    fn is_full(&self) -> bool {
        self.vacant_len() == 0
    }
}

/// Trait used for delegating observer methods.
pub trait DelegateObserver: Based
where
    Self::Base: Observer,
{
}

impl<D: DelegateObserver> Observer for D
where
    D::Base: Observer,
{
    type Item = <D::Base as Observer>::Item;

    #[inline]
    fn capacity(&self) -> NonZeroUsize {
        self.base().capacity()
    }

    #[inline]
    fn read_index(&self) -> usize {
        self.base().read_index()
    }
    #[inline]
    fn write_index(&self) -> usize {
        self.base().write_index()
    }

    #[inline]
    unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]) {
        self.base().unsafe_slices(start, end)
    }
    #[inline]
    unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]) {
        self.base().unsafe_slices_mut(start, end)
    }

    #[inline]
    fn read_is_held(&self) -> bool {
        self.base().read_is_held()
    }
    #[inline]
    fn write_is_held(&self) -> bool {
        self.base().write_is_held()
    }

    #[inline]
    fn occupied_len(&self) -> usize {
        self.base().occupied_len()
    }

    #[inline]
    fn vacant_len(&self) -> usize {
        self.base().vacant_len()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.base().is_empty()
    }

    #[inline]
    fn is_full(&self) -> bool {
        self.base().is_full()
    }
}