gosuto_livekit/room/utils/
take_cell.rs1use parking_lot::RwLock;
16use std::{fmt::Debug, sync::Arc};
17
18pub struct TakeCell<T> {
21 value: Arc<RwLock<Option<T>>>,
22}
23
24impl<T> TakeCell<T> {
25 pub(crate) fn new(value: T) -> Self {
26 Self { value: Arc::new(RwLock::new(Some(value))) }
27 }
28
29 pub(crate) fn take_if_raw(&self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
34 if self.value.read().as_ref().map_or(false, |v| predicate(v)) {
35 self.take()
36 } else {
37 None
38 }
39 }
40
41 pub fn take(&self) -> Option<T> {
44 self.value.write().take()
45 }
46
47 pub fn is_taken(&self) -> bool {
49 self.value.read().is_none()
50 }
51}
52
53impl<T> Debug for TakeCell<T>
54where
55 T: Debug,
56{
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 let inner = self.value.read();
59 f.debug_struct("TakeCell")
60 .field(
61 "value",
62 &inner.as_ref().map(|v| v as &dyn Debug).unwrap_or(&"<taken>" as &dyn Debug),
63 )
64 .finish()
65 }
66}
67
68impl<T> Clone for TakeCell<T> {
69 fn clone(&self) -> Self {
70 Self { value: self.value.clone() }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 #[test]
78 fn test_take() {
79 let cell = TakeCell::new(1);
80 assert_eq!(cell.is_taken(), false);
81 assert_eq!(cell.take(), Some(1));
82 assert_eq!(cell.take(), None);
83 assert_eq!(cell.is_taken(), true);
84 }
85
86 #[test]
87 fn test_take_if_raw() {
88 let cell = TakeCell::new(1);
89 assert_eq!(cell.take_if_raw(|value| *value == 2), None);
90 assert_eq!(cell.take_if_raw(|value| *value == 1), Some(1));
91 assert_eq!(cell.take_if_raw(|value| *value == 1), None);
92 }
93
94 #[test]
95 fn test_debug() {
96 let cell = TakeCell::new(1);
97 assert_eq!(format!("{:?}", cell), "TakeCell { value: 1 }");
98
99 cell.take();
100 assert_eq!(format!("{:?}", cell), "TakeCell { value: \"<taken>\" }");
101 }
102}