output_tracker/non_threadsafe/
mod.rs1use crate::inner_subject::{BasicSubject, CelledSubject};
6use crate::inner_tracker::{BasicTracker, CelledTracker};
7use crate::non_threadsafe::Error::{BorrowMutTrackerFailed, BorrowTrackerFailed};
8use crate::tracker_handle::TrackerHandle;
9use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
10use std::rc::Rc;
11
12#[derive(thiserror::Error, Debug)]
14pub enum Error {
15 #[error("failed to obtain an immutable borrow of the tracker, reason: {0}")]
17 BorrowTrackerFailed(BorrowError),
18 #[error("failed to obtain a mutable borrow of the tracker, reason: {0}")]
20 BorrowMutTrackerFailed(BorrowMutError),
21 #[error("failed to obtain an immutable borrow of the subject, reason: {0}")]
23 BorrowSubjectFailed(BorrowError),
24 #[error("failed to obtain a mutable borrow of the subject, reason: {0}")]
26 BorrowMutSubjectFailed(BorrowMutError),
27}
28
29#[derive(Debug)]
43pub struct OutputTracker<M> {
44 handle: TrackerHandle,
45 inner: NonThreadsafeTracker<M>,
46 subject: NonThreadsafeSubject<M>,
47}
48
49impl<M> OutputTracker<M> {
50 const fn new(
51 handle: TrackerHandle,
52 inner: NonThreadsafeTracker<M>,
53 subject: NonThreadsafeSubject<M>,
54 ) -> Self {
55 Self {
56 handle,
57 inner,
58 subject,
59 }
60 }
61
62 pub fn stop(&self) -> Result<(), Error> {
67 self.subject.remove_tracker(self.handle)
68 }
69
70 pub fn clear(&self) -> Result<(), Error> {
75 self.inner.clear()
76 }
77
78 pub fn output(&self) -> Result<Vec<M>, Error>
87 where
88 M: Clone,
89 {
90 self.inner.output()
91 }
92}
93
94#[derive(Default, Debug, Clone)]
104pub struct OutputSubject<M> {
105 inner: NonThreadsafeSubject<M>,
106}
107
108impl<M> OutputSubject<M> {
109 #[must_use]
114 pub fn new() -> Self {
115 Self {
116 inner: NonThreadsafeSubject::new(),
117 }
118 }
119}
120
121impl<M> OutputSubject<M>
122where
123 M: Clone,
124{
125 pub fn create_tracker(&self) -> Result<OutputTracker<M>, Error> {
128 let new_tracker = NonThreadsafeTracker::new();
129 let handle = self.inner.add_tracker(new_tracker.clone())?;
130 Ok(OutputTracker::new(handle, new_tracker, self.inner.clone()))
131 }
132
133 pub fn emit(&self, data: M) -> Result<(), Error> {
137 self.inner.emit(data)
138 }
139}
140
141#[derive(Default, Debug, Clone)]
142struct NonThreadsafeSubject<M> {
143 cell: Rc<RefCell<BasicSubject<M, NonThreadsafeTracker<M>>>>,
144}
145
146impl<M> NonThreadsafeSubject<M> {
147 fn new() -> Self {
148 Self {
149 cell: Rc::new(RefCell::new(BasicSubject::new())),
150 }
151 }
152}
153
154impl<M> CelledSubject<M, NonThreadsafeTracker<M>> for NonThreadsafeSubject<M> {
155 type Inner<'a>
156 = Ref<'a, BasicSubject<M, NonThreadsafeTracker<M>>>
157 where
158 M: 'a;
159 type InnerMut<'a>
160 = RefMut<'a, BasicSubject<M, NonThreadsafeTracker<M>>>
161 where
162 M: 'a;
163 type Error = Error;
164
165 fn subject(&self) -> Result<Self::Inner<'_>, Error> {
166 self.cell.try_borrow().map_err(Error::BorrowSubjectFailed)
167 }
168
169 fn subject_mut(&self) -> Result<Self::InnerMut<'_>, Error> {
170 self.cell
171 .try_borrow_mut()
172 .map_err(Error::BorrowMutSubjectFailed)
173 }
174}
175
176#[derive(Debug, Clone)]
177struct NonThreadsafeTracker<M> {
178 cell: Rc<RefCell<BasicTracker<M>>>,
179}
180
181impl<M> CelledTracker<M> for NonThreadsafeTracker<M> {
182 type Inner<'a>
183 = Ref<'a, BasicTracker<M>>
184 where
185 Self: 'a;
186 type InnerMut<'a>
187 = RefMut<'a, BasicTracker<M>>
188 where
189 Self: 'a;
190 type Error = Error;
191
192 fn new() -> Self {
193 Self {
194 cell: Rc::new(RefCell::new(BasicTracker::new())),
195 }
196 }
197
198 fn tracker(&self) -> Result<Self::Inner<'_>, Self::Error> {
199 self.cell.try_borrow().map_err(BorrowTrackerFailed)
200 }
201
202 fn tracker_mut(&self) -> Result<Self::InnerMut<'_>, Self::Error> {
203 self.cell.try_borrow_mut().map_err(BorrowMutTrackerFailed)
204 }
205}
206
207#[cfg(test)]
208mod tests;