Coverage Report

Created: 2026-04-14 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sync_wrapper-1.0.2/src/lib.rs
Line
Count
Source
1
/*
2
 * Copyright 2020 Actyx AG
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
//! A mutual exclusion primitive that relies on static type information only
17
//!
18
//! This library is inspired by [this discussion](https://internals.rust-lang.org/t/what-shall-sync-mean-across-an-await/12020/2).
19
#![doc(html_logo_url = "https://developer.actyx.com/img/logo.svg")]
20
#![doc(html_favicon_url = "https://developer.actyx.com/img/favicon.ico")]
21
#![no_std]
22
23
use core::{
24
    fmt::{self, Debug, Formatter},
25
    pin::Pin,
26
    future::Future,
27
    task::{Context, Poll},
28
};
29
30
/// A mutual exclusion primitive that relies on static type information only
31
///
32
/// In some cases synchronization can be proven statically: whenever you hold an exclusive `&mut`
33
/// reference, the Rust type system ensures that no other part of the program can hold another
34
/// reference to the data. Therefore it is safe to access it even if the current thread obtained
35
/// this reference via a channel. Whenever this is the case, the overhead of allocating and locking
36
/// a [`Mutex`] can be avoided by using this static version.
37
///
38
/// One example where this is often applicable is [`Future`], which requires an exclusive reference
39
/// for its [`poll`] method: While a given `Future` implementation may not be safe to access by
40
/// multiple threads concurrently, the executor can only run the `Future` on one thread at any
41
/// given time, making it [`Sync`] in practice as long as the implementation is `Send`. You can
42
/// therefore use the static mutex to prove that your data structure is `Sync` even though it
43
/// contains such a `Future`.
44
///
45
/// # Example
46
///
47
/// ```
48
/// use sync_wrapper::SyncWrapper;
49
/// use std::future::Future;
50
///
51
/// struct MyThing {
52
///     future: SyncWrapper<Box<dyn Future<Output = String> + Send>>,
53
/// }
54
///
55
/// impl MyThing {
56
///     // all accesses to `self.future` now require an exclusive reference or ownership
57
/// }
58
///
59
/// fn assert_sync<T: Sync>() {}
60
///
61
/// assert_sync::<MyThing>();
62
/// ```
63
///
64
/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
65
/// [`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
66
/// [`poll`]: https://doc.rust-lang.org/std/future/trait.Future.html#method.poll
67
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
68
#[repr(transparent)]
69
pub struct SyncWrapper<T>(T);
70
71
impl<T> SyncWrapper<T> {
72
    /// Creates a new static mutex containing the given value.
73
    ///
74
    /// # Examples
75
    ///
76
    /// ```
77
    /// use sync_wrapper::SyncWrapper;
78
    ///
79
    /// let mutex = SyncWrapper::new(42);
80
    /// ```
81
0
    pub const fn new(value: T) -> Self {
82
0
        Self(value)
83
0
    }
Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::istio::ca::IstioCertificateResponse, Error = tonic::status::Status> + core::marker::Send>>>::new
Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::service::discovery::v3::DeltaDiscoveryResponse, Error = tonic::status::Status> + core::marker::Send>>>::new
Unexecuted instantiation: <sync_wrapper::SyncWrapper<tonic::body::Body>>::new
84
85
    /// Acquires a reference to the protected value.
86
    ///
87
    /// This is safe because it requires an exclusive reference to the mutex. Therefore this method
88
    /// neither panics nor does it return an error. This is in contrast to [`Mutex::get_mut`] which
89
    /// returns an error if another thread panicked while holding the lock. It is not recommended
90
    /// to send an exclusive reference to a potentially damaged value to another thread for further
91
    /// processing.
92
    ///
93
    /// [`Mutex::get_mut`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get_mut
94
    ///
95
    /// # Examples
96
    ///
97
    /// ```
98
    /// use sync_wrapper::SyncWrapper;
99
    ///
100
    /// let mut mutex = SyncWrapper::new(42);
101
    /// let value = mutex.get_mut();
102
    /// *value = 0;
103
    /// assert_eq!(*mutex.get_mut(), 0);
104
    /// ```
105
0
    pub fn get_mut(&mut self) -> &mut T {
106
0
        &mut self.0
107
0
    }
Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::istio::ca::IstioCertificateResponse, Error = tonic::status::Status> + core::marker::Send>>>::get_mut
Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::service::discovery::v3::DeltaDiscoveryResponse, Error = tonic::status::Status> + core::marker::Send>>>::get_mut
Unexecuted instantiation: <sync_wrapper::SyncWrapper<tonic::body::Body>>::get_mut
108
109
    /// Acquires a pinned reference to the protected value.
110
    ///
111
    /// See [`Self::get_mut`] for why this method is safe.
112
    ///
113
    /// # Examples
114
    ///
115
    /// ```
116
    /// use std::future::Future;
117
    /// use std::pin::Pin;
118
    /// use std::task::{Context, Poll};
119
    ///
120
    /// use pin_project_lite::pin_project;
121
    /// use sync_wrapper::SyncWrapper;
122
    ///
123
    /// pin_project! {
124
    ///     struct FutureWrapper<F> {
125
    ///         #[pin]
126
    ///         inner: SyncWrapper<F>,
127
    ///     }
128
    /// }
129
    ///
130
    /// impl<F: Future> Future for FutureWrapper<F> {
131
    ///     type Output = F::Output;
132
    ///
133
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
134
    ///         self.project().inner.get_pin_mut().poll(cx)
135
    ///     }
136
    /// }
137
    /// ```
138
    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
139
        unsafe { Pin::map_unchecked_mut(self, |this| &mut this.0) }
140
    }
141
142
    /// Consumes this mutex, returning the underlying data.
143
    ///
144
    /// This is safe because it requires ownership of the mutex, therefore this method will neither
145
    /// panic nor does it return an error. This is in contrast to [`Mutex::into_inner`] which
146
    /// returns an error if another thread panicked while holding the lock. It is not recommended
147
    /// to send an exclusive reference to a potentially damaged value to another thread for further
148
    /// processing.
149
    ///
150
    /// [`Mutex::into_inner`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.into_inner
151
    ///
152
    /// # Examples
153
    ///
154
    /// ```
155
    /// use sync_wrapper::SyncWrapper;
156
    ///
157
    /// let mut mutex = SyncWrapper::new(42);
158
    /// assert_eq!(mutex.into_inner(), 42);
159
    /// ```
160
    pub fn into_inner(self) -> T {
161
        self.0
162
    }
163
}
164
165
// this is safe because the only operations permitted on this data structure require exclusive
166
// access or ownership
167
unsafe impl<T> Sync for SyncWrapper<T> {}
168
169
impl<T> Debug for SyncWrapper<T> {
170
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
171
        f.pad("SyncWrapper")
172
    }
173
}
174
175
impl<T: Default> Default for SyncWrapper<T> {
176
    fn default() -> Self {
177
        Self::new(T::default())
178
    }
179
}
180
181
impl<T> From<T> for SyncWrapper<T> {
182
    fn from(value: T) -> Self {
183
        Self::new(value)
184
    }
185
}
186
187
/// `Future` which is `Sync`.
188
///
189
/// # Examples
190
///
191
/// ```
192
/// use sync_wrapper::{SyncWrapper, SyncFuture};
193
///
194
/// let fut = async { 1 };
195
/// let fut = SyncFuture::new(fut);
196
/// ```
197
pub struct SyncFuture<F> {
198
    inner: SyncWrapper<F>
199
}
200
impl <F: Future> SyncFuture<F> {
201
    pub fn new(inner: F) -> Self {
202
        Self { inner: SyncWrapper::new(inner) }
203
    }
204
    pub fn into_inner(self) -> F {
205
        self.inner.into_inner()
206
    }
207
}
208
impl <F: Future> Future for SyncFuture<F> {
209
    type Output = F::Output;
210
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
211
        let inner = unsafe { self.map_unchecked_mut(|x| x.inner.get_mut()) };
212
        inner.poll(cx)
213
    }
214
}
215
impl<T> Debug for SyncFuture<T> {
216
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
217
        f.pad("SyncFuture")
218
    }
219
}
220
221
/// `Stream` which is `Sync`.
222
///
223
/// # Examples
224
///
225
/// ```
226
/// use sync_wrapper::SyncStream;
227
/// use futures::stream;
228
///
229
/// let st = stream::iter(vec![1]);
230
/// let st = SyncStream::new(st);
231
/// ```
232
#[cfg(feature = "futures")]
233
pub struct SyncStream<S> {
234
    inner: SyncWrapper<S>
235
}
236
#[cfg(feature = "futures")]
237
impl <S: futures_core::Stream> SyncStream<S> {
238
    pub fn new(inner: S) -> Self {
239
        Self { inner: SyncWrapper::new(inner) }
240
    }
241
    pub fn into_inner(self) -> S {
242
        self.inner.into_inner()
243
    }
244
}
245
#[cfg(feature = "futures")]
246
impl <S: futures_core::Stream> futures_core::Stream for SyncStream<S> {
247
    type Item = S::Item;
248
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
249
        let inner = unsafe { self.map_unchecked_mut(|x| x.inner.get_mut()) };
250
        inner.poll_next(cx)
251
    }
252
}
253
#[cfg(feature = "futures")]
254
impl<T> Debug for SyncStream<T> {
255
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
256
        f.pad("SyncStream")
257
    }
258
}