orx_concurrent_vec/elem.rs
1use orx_concurrent_option::ConcurrentOption;
2
3/// An element of the `ConcurrentVec` that provides thread safe
4/// read and write methods on the value of the element.
5///
6/// A concurrent element can be created by using the index operator `vec[i]`
7/// or calling [`vec.get(i)`] or [`vec.iter()`] on a concurrent vec or slice.
8///
9/// [`vec.get(i)`]: crate::ConcurrentVec::get
10/// [`vec.iter()`]: crate::ConcurrentVec::iter
11pub struct ConcurrentElement<T>(pub(crate) ConcurrentOption<T>);
12
13impl<T> From<ConcurrentOption<T>> for ConcurrentElement<T> {
14 fn from(value: ConcurrentOption<T>) -> Self {
15 Self(value)
16 }
17}
18
19impl<T> ConcurrentElement<T> {
20 /// Returns a clone of value of the element.
21 ///
22 /// # Examples
23 ///
24 /// ```rust
25 /// use orx_concurrent_vec::*;
26 ///
27 /// let vec = ConcurrentVec::new();
28 /// vec.extend(["foo", "bar"].map(|x| x.to_string()));
29 ///
30 /// assert_eq!(vec[0].cloned(), "foo".to_string());
31 /// assert_eq!(vec[1].cloned(), "bar".to_string());
32 ///
33 /// vec[1].set("baz".to_string());
34 /// assert_eq!(vec[1].cloned(), "baz".to_string());
35 /// ```
36 #[inline(always)]
37 #[allow(clippy::missing_panics_doc)]
38 pub fn cloned(&self) -> T
39 where
40 T: Clone,
41 {
42 self.0.clone_into_option().expect(HAS_VALUE)
43 }
44
45 /// Returns a copy of value of the element.
46 ///
47 /// # Examples
48 ///
49 /// ```rust
50 /// use orx_concurrent_vec::*;
51 ///
52 /// let vec = ConcurrentVec::new();
53 /// vec.extend([42, 7]);
54 ///
55 /// assert_eq!(vec[0].copied(), 42);
56 /// assert_eq!(vec[1].copied(), 7);
57 ///
58 /// vec[1].set(0);
59 /// assert_eq!(vec[1].copied(), 0);
60 /// ```
61 #[inline(always)]
62 #[allow(clippy::missing_panics_doc)]
63 pub fn copied(&self) -> T
64 where
65 T: Copy,
66 {
67 self.0.clone_into_option().expect(HAS_VALUE)
68 }
69
70 /// Maps the value and returns the result of `f(&element)`.
71 ///
72 /// # Examples
73 ///
74 /// ```rust
75 /// use orx_concurrent_vec::*;
76 ///
77 /// let vec: ConcurrentVec<_> = [0, 1, 2, 3].into_iter().collect();
78 ///
79 /// let one = vec[1].map(|x| x.to_string());
80 /// assert_eq!(one, 1.to_string());
81 ///
82 /// let doubles: Vec<_> = vec.iter().map(|elem| elem.map(|x| x * 2)).collect();
83 /// assert_eq!(doubles, [0, 2, 4, 6]);
84 ///
85 /// let mut sum = 0;
86 /// for i in 0..vec.len() {
87 /// vec[i].map(|x| {
88 /// sum += x;
89 /// });
90 /// }
91 /// assert_eq!(sum, 6);
92 /// ```
93 #[inline(always)]
94 #[allow(clippy::missing_panics_doc)]
95 pub fn map<F, U>(&self, f: F) -> U
96 where
97 F: FnOnce(&T) -> U,
98 {
99 self.0.map(f).expect(HAS_VALUE)
100 }
101
102 // mut
103
104 /// Replaces the current value of the element
105 /// with the given `value`, and returns the old value.
106 ///
107 /// See also [`set`] if the old value is to be omitted.
108 ///
109 /// [`set`]: crate::ConcurrentElement::set
110 ///
111 /// # Examples
112 ///
113 /// ```rust
114 /// use orx_concurrent_vec::*;
115 ///
116 /// let vec = ConcurrentVec::from_iter(['a', 'b', 'c', 'd']);
117 ///
118 /// let c = vec[2].replace('x');
119 ///
120 /// assert_eq!(c, 'c');
121 /// assert_eq!(&vec, &['a', 'b', 'x', 'd']);
122 /// ```
123 #[inline(always)]
124 #[allow(clippy::missing_panics_doc)]
125 pub fn replace(&self, value: T) -> T {
126 self.0.replace(value).expect(HAS_VALUE)
127 }
128
129 /// Sets (overwrites) value of the element with the given `value`.
130 ///
131 /// See also [`replace`] if the old value is required.
132 ///
133 /// [`replace`]: crate::ConcurrentElement::replace
134 ///
135 /// # Examples
136 ///
137 /// ```rust
138 /// use orx_concurrent_vec::*;
139 ///
140 /// let vec = ConcurrentVec::new();
141 /// vec.extend(['a', 'b', 'c', 'd']);
142 ///
143 /// vec[2].set('x');
144 /// assert_eq!(&vec, &['a', 'b', 'x', 'd']);
145 /// ```
146 #[inline(always)]
147 #[allow(clippy::missing_panics_doc)]
148 pub fn set(&self, value: T) {
149 assert!(self.0.set_some(value), "Failed to set the element");
150 }
151
152 /// Updates the current value of the element by calling the mutating
153 /// function `f(&mut element)`.
154 ///
155 /// # Examples
156 ///
157 /// ```rust
158 /// use orx_concurrent_vec::*;
159 ///
160 /// let vec = ConcurrentVec::from_iter([0, 1, 2, 3]);
161 ///
162 /// vec[1].update(|x| *x *= 2);
163 /// vec[2].update(|x| *x += 10);
164 /// vec[3].update(|x| *x = 7);
165 ///
166 /// assert_eq!(&vec, &[0, 2, 12, 7]);
167 /// ```
168 #[inline(always)]
169 #[allow(clippy::missing_panics_doc)]
170 pub fn update<F>(&self, f: F)
171 where
172 F: FnMut(&mut T),
173 {
174 assert!(self.0.update_if_some(f), "Failed to update the element");
175 }
176}
177
178// constants
179
180const HAS_VALUE: &str = "ConcurrentElement must always have a value";