1use super::{
2 macros::rb_impl_init,
3 utils::{assert_capacity, ranges},
4};
5#[cfg(feature = "alloc")]
6use crate::traits::Split;
7use crate::{
8 storage::Storage,
9 traits::{
10 Observer, RingBuffer, SplitRef,
11 consumer::{Consumer, impl_consumer_traits},
12 producer::{Producer, impl_producer_traits},
13 },
14 wrap::{Cons, Prod},
15};
16#[cfg(feature = "alloc")]
17use alloc::{boxed::Box, rc::Rc};
18use core::{
19 cell::Cell,
20 mem::{ManuallyDrop, MaybeUninit},
21 num::NonZeroUsize,
22 ptr,
23};
24
25struct Endpoint {
26 index: Cell<usize>,
27 held: Cell<bool>,
28}
29
30impl Endpoint {
31 const fn new(index: usize) -> Self {
32 Self {
33 index: Cell::new(index),
34 held: Cell::new(false),
35 }
36 }
37}
38
39pub struct LocalRb<S: Storage + ?Sized> {
43 read: Endpoint,
44 write: Endpoint,
45 storage: S,
46}
47
48impl<S: Storage> LocalRb<S> {
49 pub unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self {
58 assert_capacity(storage.len());
59 Self {
60 storage,
61 read: Endpoint::new(read),
62 write: Endpoint::new(write),
63 }
64 }
65 pub unsafe fn into_raw_parts(self) -> (S, usize, usize) {
71 let this = ManuallyDrop::new(self);
72 (unsafe { ptr::read(&this.storage) }, this.read_index(), this.write_index())
73 }
74}
75
76impl<S: Storage + ?Sized> Observer for LocalRb<S> {
77 type Item = S::Item;
78
79 #[inline]
80 fn capacity(&self) -> NonZeroUsize {
81 unsafe { NonZeroUsize::new_unchecked(self.storage.len()) }
82 }
83
84 #[inline]
85 fn read_index(&self) -> usize {
86 self.read.index.get()
87 }
88 #[inline]
89 fn write_index(&self) -> usize {
90 self.write.index.get()
91 }
92
93 unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<S::Item>], &[MaybeUninit<S::Item>]) {
94 let (first, second) = ranges(self.capacity(), start, end);
95 unsafe { (self.storage.slice(first), self.storage.slice(second)) }
96 }
97 unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<S::Item>], &mut [MaybeUninit<S::Item>]) {
98 let (first, second) = ranges(self.capacity(), start, end);
99 unsafe { (self.storage.slice_mut(first), self.storage.slice_mut(second)) }
100 }
101
102 #[inline]
103 fn read_is_held(&self) -> bool {
104 self.read.held.get()
105 }
106 #[inline]
107 fn write_is_held(&self) -> bool {
108 self.write.held.get()
109 }
110}
111
112impl<S: Storage + ?Sized> Producer for LocalRb<S> {
113 #[inline]
114 unsafe fn set_write_index(&self, value: usize) {
115 self.write.index.set(value);
116 }
117}
118
119impl<S: Storage + ?Sized> Consumer for LocalRb<S> {
120 #[inline]
121 unsafe fn set_read_index(&self, value: usize) {
122 self.read.index.set(value);
123 }
124}
125
126impl<S: Storage + ?Sized> RingBuffer for LocalRb<S> {
127 #[inline]
128 unsafe fn hold_read(&self, flag: bool) -> bool {
129 self.read.held.replace(flag)
130 }
131 #[inline]
132 unsafe fn hold_write(&self, flag: bool) -> bool {
133 self.write.held.replace(flag)
134 }
135}
136
137impl<S: Storage + ?Sized> Drop for LocalRb<S> {
138 fn drop(&mut self) {
139 self.clear();
140 }
141}
142
143#[cfg(feature = "alloc")]
144impl<S: Storage> Split for LocalRb<S> {
145 type Prod = Prod<Rc<Self>>;
146 type Cons = Cons<Rc<Self>>;
147
148 fn split(self) -> (Self::Prod, Self::Cons) {
149 Rc::new(self).split()
150 }
151}
152#[cfg(feature = "alloc")]
153impl<S: Storage + ?Sized> Split for Rc<LocalRb<S>> {
154 type Prod = Prod<Self>;
155 type Cons = Cons<Self>;
156
157 fn split(self) -> (Self::Prod, Self::Cons) {
158 (Prod::new(self.clone()), Cons::new(self))
159 }
160}
161#[cfg(feature = "alloc")]
162impl<S: Storage + ?Sized> Split for Box<LocalRb<S>> {
163 type Prod = Prod<Rc<LocalRb<S>>>;
164 type Cons = Cons<Rc<LocalRb<S>>>;
165
166 fn split(self) -> (Self::Prod, Self::Cons) {
167 Rc::<LocalRb<S>>::from(self).split()
168 }
169}
170impl<S: Storage + ?Sized> SplitRef for LocalRb<S> {
171 type RefProd<'a>
172 = Prod<&'a Self>
173 where
174 Self: 'a;
175 type RefCons<'a>
176 = Cons<&'a Self>
177 where
178 Self: 'a;
179
180 fn split_ref(&mut self) -> (Self::RefProd<'_>, Self::RefCons<'_>) {
181 (Prod::new(self), Cons::new(self))
182 }
183}
184
185rb_impl_init!(LocalRb);
186
187impl_producer_traits!(LocalRb<S: Storage>);
188impl_consumer_traits!(LocalRb<S: Storage>);
189
190impl<S: Storage + ?Sized> AsRef<Self> for LocalRb<S> {
191 fn as_ref(&self) -> &Self {
192 self
193 }
194}
195impl<S: Storage + ?Sized> AsMut<Self> for LocalRb<S> {
196 fn as_mut(&mut self) -> &mut Self {
197 self
198 }
199}