abi_stable/external_types/crossbeam_channel.rs
1//! Ffi-safe wrapper types around the
2//! [crossbeam-channel](https://crates.io/crates/crossbeam-channel/)
3//! channel types.
4#![allow(clippy::missing_const_for_fn)]
5
6use std::{
7 fmt::{self, Debug},
8 marker::PhantomData,
9 time::Duration,
10};
11
12use crossbeam_channel::{
13 Receiver, RecvError, RecvTimeoutError, SendError, SendTimeoutError, Sender, TryRecvError,
14 TrySendError,
15};
16
17use core_extensions::SelfOps;
18
19use crate::{
20 marker_type::UnsafeIgnoredType,
21 pointer_trait::AsPtr,
22 prefix_type::WithMetadata,
23 sabi_types::RRef,
24 std_types::{RBox, RDuration, RErr, ROk, ROption, RResult},
25 traits::{ErasedType, IntoReprRust},
26};
27
28mod errors;
29mod extern_fns;
30mod iteration;
31
32#[cfg(all(test, not(feature = "test_miri_track_raw")))]
33mod tests;
34
35use self::errors::{
36 RRecvError, RRecvTimeoutError, RSendError, RSendTimeoutError, RTryRecvError, RTrySendError,
37};
38
39pub use self::iteration::{RIntoIter, RIter};
40
41///////////////////////////////////////////////////////////////////////////////
42
43/// Creates a receiver that can never receive any value.
44///
45/// # Example
46///
47#[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
48#[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
49/// use abi_stable::external_types::crossbeam_channel as mpmc;
50///
51/// let rx = mpmc::never::<()>();
52///
53/// assert_eq!(rx.try_recv().ok(), None);
54///
55/// ```
56pub fn never<T>() -> RReceiver<T> {
57 crossbeam_channel::never::<T>().into()
58}
59
60/// Creates a channel which can hold up to `capacity` elements in its internal queue.
61///
62/// If `capacity==0`,the value must be sent to a receiver in the middle of a `recv` call.
63///
64/// # Panics
65///
66/// Panics if `capacity >= usize::max_value() / 4`.
67///
68/// # Example
69///
70#[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
71#[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
72/// use abi_stable::external_types::crossbeam_channel as mpmc;
73///
74/// let (tx, rx) = mpmc::bounded::<u32>(3);
75///
76/// std::thread::spawn(move || {
77/// tx.send(10).unwrap();
78/// tx.send(11).unwrap();
79/// tx.send(12).unwrap();
80/// });
81///
82/// assert_eq!(rx.recv().unwrap(), 10);
83/// assert_eq!(rx.recv().unwrap(), 11);
84/// assert_eq!(rx.recv().unwrap(), 12);
85/// assert!(rx.try_recv().is_err());
86///
87/// ```
88///
89pub fn bounded<T>(capacity: usize) -> (RSender<T>, RReceiver<T>) {
90 let (tx, rx) = crossbeam_channel::bounded::<T>(capacity);
91 (tx.into(), rx.into())
92}
93
94/// Creates a channel which can hold an unbounded amount elements in its internal queue.
95///
96/// # Example
97///
98#[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
99#[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
100/// use abi_stable::external_types::crossbeam_channel as mpmc;
101///
102/// let (tx, rx) = mpmc::unbounded::<&'static str>();
103///
104/// let join_guard = std::thread::spawn(move || {
105/// assert_eq!(rx.recv().unwrap(), "foo");
106/// assert_eq!(rx.recv().unwrap(), "bar");
107/// assert_eq!(rx.recv().unwrap(), "baz");
108/// assert!(rx.try_recv().is_err());
109/// });
110///
111/// tx.send("foo").unwrap();
112/// tx.send("bar").unwrap();
113/// tx.send("baz").unwrap();
114///
115/// join_guard.join().unwrap();
116///
117/// ```
118///
119///
120pub fn unbounded<T>() -> (RSender<T>, RReceiver<T>) {
121 let (tx, rx) = crossbeam_channel::unbounded::<T>();
122 (tx.into(), rx.into())
123}
124
125///////////////////////////////////////////////////////////////////////////////
126
127/// The sender end of a channel,
128/// which can be either bounded or unbounded.
129///
130/// # Example
131///
132#[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
133#[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
134/// use abi_stable::external_types::crossbeam_channel as mpmc;
135///
136/// let (tx, rx) = mpmc::bounded::<&'static str>(1024);
137///
138/// std::thread::spawn(move || {
139/// for _ in 0..4 {
140/// tx.send("Are we there yet.").unwrap();
141/// }
142/// });
143///
144/// assert_eq!(rx.recv().unwrap(), "Are we there yet.");
145/// assert_eq!(rx.recv().unwrap(), "Are we there yet.");
146/// assert_eq!(rx.recv().unwrap(), "Are we there yet.");
147/// assert_eq!(rx.recv().unwrap(), "Are we there yet.");
148/// assert!(rx.recv().is_err());
149///
150///
151/// ```
152///
153///
154#[repr(C)]
155#[derive(StableAbi)]
156pub struct RSender<T> {
157 channel: RBox<ErasedSender<T>>,
158 vtable: VTable_Ref<T>,
159}
160
161impl<T> RSender<T> {
162 fn vtable(&self) -> VTable_Ref<T> {
163 self.vtable
164 }
165
166 /// Blocks until `value` is either sent,or the the other end is disconnected.
167 ///
168 /// If the channel queue is full,this will block to send `value`.
169 ///
170 /// If the channel is disconnected,this will return an error with `value`.
171 ///
172 /// # Example
173 ///
174 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
175 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
176 /// use abi_stable::external_types::crossbeam_channel as mpmc;
177 ///
178 /// let (tx, rx) = mpmc::bounded::<u32>(3);
179 ///
180 /// tx.send(1057).unwrap();
181 ///
182 /// drop(rx);
183 /// assert!(tx.send(0).is_err());
184 ///
185 /// ```
186 ///
187 pub fn send(&self, value: T) -> Result<(), SendError<T>> {
188 let vtable = self.vtable();
189
190 vtable.send()(self.channel.as_rref(), value).piped(result_from)
191 }
192
193 /// Immediately sends `value`,or returns with an error.
194 ///
195 /// An error will be returned in these 2 conditions:
196 ///
197 /// - the channel is full.
198 ///
199 /// - the channel has been disconnected.
200 ///
201 /// If the channel has a capacity of 0,it will only send `value` if
202 /// the other end is calling `recv`.
203 ///
204 /// # Example
205 ///
206 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
207 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
208 /// use abi_stable::external_types::crossbeam_channel as mpmc;
209 ///
210 /// let (tx, rx) = mpmc::bounded::<bool>(1);
211 ///
212 /// tx.try_send(true).unwrap();
213 /// assert!(tx.try_send(true).unwrap_err().is_full());
214 ///
215 /// drop(rx);
216 /// assert!(tx.try_send(false).unwrap_err().is_disconnected());
217 ///
218 /// ```
219 ///
220 ///
221 pub fn try_send(&self, value: T) -> Result<(), TrySendError<T>> {
222 let vtable = self.vtable();
223
224 vtable.try_send()(self.channel.as_rref(), value).piped(result_from)
225 }
226
227 /// Blocks until a timeout to send `value`.
228 ///
229 /// An error will be returned in these 2 conditions:
230 ///
231 /// - the value could not be sent before the timeout.
232 ///
233 /// - the channel has been disconnected.
234 ///
235 /// If the channel has a capacity of 0,it will only send `value` if
236 /// the other end calls `recv` before the timeout.
237 ///
238 /// # Example
239 ///
240 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
241 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
242 /// use abi_stable::external_types::crossbeam_channel as mpmc;
243 ///
244 /// use std::time::Duration;
245 ///
246 /// let (tx, rx) = mpmc::bounded::<()>(1);
247 ///
248 /// let timeout = Duration::from_millis(1);
249 ///
250 /// tx.send_timeout((), timeout).unwrap();
251 /// assert!(tx.send_timeout((), timeout).unwrap_err().is_timeout());
252 ///
253 /// drop(rx);
254 /// assert!(tx.send_timeout((), timeout).unwrap_err().is_disconnected());
255 ///
256 /// ```
257 ///
258 pub fn send_timeout(&self, value: T, timeout: Duration) -> Result<(), SendTimeoutError<T>> {
259 let vtable = self.vtable();
260
261 vtable.send_timeout()(self.channel.as_rref(), value, timeout.into()).piped(result_from)
262 }
263
264 /// Returns true if there are no values in the channel queue.
265 ///
266 /// # Example
267 ///
268 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
269 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
270 /// use abi_stable::external_types::crossbeam_channel as mpmc;
271 ///
272 /// let (tx, rx) = mpmc::bounded::<()>(1);
273 ///
274 /// assert!(tx.is_empty());
275 ///
276 /// tx.send(()).unwrap();
277 /// assert!(!tx.is_empty());
278 ///
279 /// rx.recv().unwrap();
280 /// assert!(tx.is_empty());
281 /// ```
282 pub fn is_empty(&self) -> bool {
283 let vtable = self.vtable();
284
285 vtable.sender_is_empty()(self.channel.as_rref())
286 }
287
288 /// Returns true if the channel queue is full.
289 ///
290 /// This always returns true for channels constructed with `bounded(0)`.
291 ///
292 /// # Example
293 ///
294 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
295 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
296 /// use abi_stable::external_types::crossbeam_channel as mpmc;
297 ///
298 /// let (tx, rx) = mpmc::bounded::<()>(2);
299 ///
300 /// assert!(!tx.is_full());
301 ///
302 /// tx.send(()).unwrap();
303 /// assert!(!tx.is_full());
304 ///
305 /// tx.send(()).unwrap();
306 /// assert!(tx.is_full());
307 ///
308 /// rx.recv().unwrap();
309 /// assert!(!tx.is_full());
310 /// ```
311 pub fn is_full(&self) -> bool {
312 let vtable = self.vtable();
313
314 vtable.sender_is_full()(self.channel.as_rref())
315 }
316
317 /// Returns the amount of values in the channel queue.
318 ///
319 /// # Example
320 ///
321 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
322 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
323 /// use abi_stable::external_types::crossbeam_channel as mpmc;
324 ///
325 /// let (tx, rx) = mpmc::bounded::<()>(2);
326 ///
327 /// assert_eq!(tx.len(), 0);
328 ///
329 /// tx.send(()).unwrap();
330 /// assert_eq!(tx.len(), 1);
331 ///
332 /// tx.send(()).unwrap();
333 /// assert_eq!(tx.len(), 2);
334 ///
335 /// rx.recv().unwrap();
336 /// assert_eq!(tx.len(), 1);
337 ///
338 /// ```
339 pub fn len(&self) -> usize {
340 let vtable = self.vtable();
341
342 vtable.sender_len()(self.channel.as_rref())
343 }
344
345 /// Returns the amount of values the channel queue can hold.
346 ///
347 /// This returns None if the channel is unbounded.
348 ///
349 /// # Example
350 ///
351 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
352 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
353 /// use abi_stable::external_types::crossbeam_channel as mpmc;
354 ///
355 /// {
356 /// let (tx, rx) = mpmc::bounded::<()>(2);
357 /// assert_eq!(tx.capacity(), Some(2));
358 /// }
359 /// {
360 /// let (tx, rx) = mpmc::unbounded::<()>();
361 /// assert_eq!(tx.capacity(), None);
362 /// }
363 ///
364 /// ```
365 pub fn capacity(&self) -> Option<usize> {
366 let vtable = self.vtable();
367
368 vtable.sender_capacity()(self.channel.as_rref()).into_rust()
369 }
370}
371
372impl<T> Clone for RSender<T> {
373 /// Clones this channel end,getting another handle into the channel.
374 ///
375 /// Note that this allocates an RBox<_>.
376 fn clone(&self) -> Self {
377 let vtable = self.vtable();
378
379 Self {
380 channel: vtable.clone_sender()(self.channel.as_rref()),
381 vtable: self.vtable,
382 }
383 }
384}
385
386impl<T> Debug for RSender<T> {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 Debug::fmt("RSender{..}", f)
389 }
390}
391
392unsafe impl<T: Send> Sync for RSender<T> {}
393
394unsafe impl<T: Send> Send for RSender<T> {}
395
396impl_from_rust_repr! {
397 impl[T] From<Sender<T>> for RSender<T> {
398 fn(this){
399 Self{
400 channel:ErasedSender::from_unerased_value(this),
401 vtable: MakeVTable::<T>::VTABLE,
402 }
403 }
404 }
405}
406
407///////////////////////////////////////////////////////////////////////////////
408
409/// The receiver end of a channel,
410/// which can be either bounded or unbounded.
411///
412/// # Examples
413///
414#[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
415#[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
416/// use abi_stable::external_types::crossbeam_channel as mpmc;
417///
418/// let (tx, rx) = mpmc::unbounded::<&'static str>();
419///
420/// let join_guard = std::thread::spawn(move || {
421/// assert_eq!(rx.recv().unwrap(), "PING");
422/// assert_eq!(rx.recv().unwrap(), "PING");
423/// assert_eq!(rx.recv().unwrap(), "PING");
424/// assert_eq!(rx.recv().unwrap(), "PING");
425/// assert!(rx.try_recv().unwrap_err().is_empty());
426/// });
427///
428/// for _ in 0..4 {
429/// tx.send("PING").unwrap();
430/// }
431///
432/// join_guard.join().unwrap();
433///
434/// assert!(tx.send("").is_err());
435///
436/// ```
437///
438#[repr(C)]
439#[derive(StableAbi)]
440pub struct RReceiver<T> {
441 channel: RBox<ErasedReceiver<T>>,
442 vtable: VTable_Ref<T>,
443}
444
445impl<T> RReceiver<T> {
446 fn vtable(&self) -> VTable_Ref<T> {
447 self.vtable
448 }
449
450 /// Blocks until a value is either received,or the the other end is disconnected.
451 ///
452 /// If the channel queue is empty,this will block to receive a value.
453 ///
454 /// This will return an error if the channel is disconnected.
455 ///
456 ///
457 /// # Example
458 ///
459 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
460 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
461 /// use abi_stable::external_types::crossbeam_channel as mpmc;
462 ///
463 /// let (tx, rx) = mpmc::bounded::<&'static str>(3);
464 ///
465 /// tx.send("J__e H____y").unwrap();
466 /// assert_eq!(rx.recv().unwrap(), "J__e H____y");
467 ///
468 /// drop(tx);
469 /// assert!(rx.recv().is_err());
470 ///
471 /// ```
472 ///
473 pub fn recv(&self) -> Result<T, RecvError> {
474 let vtable = self.vtable();
475
476 vtable.recv()(self.channel.as_rref()).piped(result_from)
477 }
478
479 /// Immediately receives a value,or returns with an error.
480 ///
481 /// An error will be returned in these 2 conditions:
482 ///
483 /// - the channel is empty.
484 ///
485 /// - the channel has been disconnected.
486 ///
487 /// If the channel has a capacity of 0,it will only receive a value if
488 /// the other end is calling `send`.
489 ///
490 ///
491 /// # Example
492 ///
493 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
494 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
495 /// use abi_stable::external_types::crossbeam_channel as mpmc;
496 ///
497 /// let (tx, rx) = mpmc::bounded::<&'static str>(3);
498 ///
499 /// assert!(rx.try_recv().is_err());
500 ///
501 /// tx.send("D__e S_____r").unwrap();
502 /// assert_eq!(rx.try_recv().unwrap(), "D__e S_____r");
503 ///
504 /// drop(tx);
505 /// assert!(rx.try_recv().is_err());
506 ///
507 /// ```
508 pub fn try_recv(&self) -> Result<T, TryRecvError> {
509 let vtable = self.vtable();
510
511 vtable.try_recv()(self.channel.as_rref()).piped(result_from)
512 }
513
514 /// Blocks until a timeout to receive a value.
515 ///
516 /// An error will be returned in these 2 conditions:
517 ///
518 /// - A value could not be received before the timeout.
519 ///
520 /// - the channel has been disconnected.
521 ///
522 /// If the channel has a capacity of 0,it will only receive a value if
523 /// the other end calls `send` before the timeout.
524 ///
525 ///
526 /// # Example
527 ///
528 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
529 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
530 /// use abi_stable::external_types::crossbeam_channel as mpmc;
531 ///
532 /// use std::time::Duration;
533 ///
534 /// let (tx, rx) = mpmc::bounded::<&'static str>(3);
535 ///
536 /// let timeout = Duration::from_millis(1);
537 ///
538 /// assert!(rx.recv_timeout(timeout).unwrap_err().is_timeout());
539 ///
540 /// tx.send("D__e S_____r").unwrap();
541 /// assert_eq!(rx.recv_timeout(timeout).unwrap(), "D__e S_____r");
542 ///
543 /// drop(tx);
544 /// assert!(rx.recv_timeout(timeout).unwrap_err().is_disconnected());
545 ///
546 /// ```
547 ///
548 pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
549 let vtable = self.vtable();
550
551 vtable.recv_timeout()(self.channel.as_rref(), timeout.into()).piped(result_from)
552 }
553
554 /// Returns true if there are no values in the channel queue.
555 ///
556 /// # Example
557 ///
558 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
559 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
560 /// use abi_stable::external_types::crossbeam_channel as mpmc;
561 ///
562 /// let (tx, rx) = mpmc::bounded::<()>(1);
563 ///
564 /// assert!(rx.is_empty());
565 ///
566 /// tx.send(()).unwrap();
567 /// assert!(!rx.is_empty());
568 ///
569 /// rx.recv().unwrap();
570 /// assert!(rx.is_empty());
571 /// ```
572 pub fn is_empty(&self) -> bool {
573 let vtable = self.vtable();
574
575 vtable.receiver_is_empty()(self.channel.as_rref())
576 }
577
578 /// Returns true if the channel queue is full.
579 ///
580 /// This always returns true for channels constructed with `bounded(0)`.
581 ///
582 /// # Example
583 ///
584 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
585 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
586 /// use abi_stable::external_types::crossbeam_channel as mpmc;
587 ///
588 /// let (tx, rx) = mpmc::bounded::<()>(2);
589 ///
590 /// assert!(!rx.is_full());
591 ///
592 /// tx.send(()).unwrap();
593 /// assert!(!rx.is_full());
594 ///
595 /// tx.send(()).unwrap();
596 /// assert!(rx.is_full());
597 ///
598 /// rx.recv().unwrap();
599 /// assert!(!rx.is_full());
600 /// ```
601 pub fn is_full(&self) -> bool {
602 let vtable = self.vtable();
603
604 vtable.receiver_is_full()(self.channel.as_rref())
605 }
606
607 /// Returns the amount of values in the channel queue.
608 ///
609 /// # Example
610 ///
611 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
612 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
613 /// use abi_stable::external_types::crossbeam_channel as mpmc;
614 ///
615 /// let (tx, rx) = mpmc::bounded::<()>(2);
616 ///
617 /// assert_eq!(rx.len(), 0);
618 ///
619 /// tx.send(()).unwrap();
620 /// assert_eq!(rx.len(), 1);
621 ///
622 /// tx.send(()).unwrap();
623 /// assert_eq!(rx.len(), 2);
624 ///
625 /// rx.recv().unwrap();
626 /// assert_eq!(rx.len(), 1);
627 ///
628 /// ```
629 pub fn len(&self) -> usize {
630 let vtable = self.vtable();
631
632 vtable.receiver_len()(self.channel.as_rref())
633 }
634
635 /// Returns the amount of values the channel queue can hold.
636 ///
637 /// This returns None if the channel is unbounded.
638 ///
639 /// # Example
640 ///
641 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
642 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
643 /// use abi_stable::external_types::crossbeam_channel as mpmc;
644 ///
645 /// {
646 /// let (tx, rx) = mpmc::bounded::<()>(2);
647 /// assert_eq!(rx.capacity(), Some(2));
648 /// }
649 /// {
650 /// let (tx, rx) = mpmc::unbounded::<()>();
651 /// assert_eq!(rx.capacity(), None);
652 /// }
653 ///
654 /// ```
655 pub fn capacity(&self) -> Option<usize> {
656 let vtable = self.vtable();
657
658 vtable.receiver_capacity()(self.channel.as_rref()).into_rust()
659 }
660
661 /// Creates an Iterator that receives values from the channel.
662 ///
663 /// # Example
664 ///
665 #[cfg_attr(not(feature = "test_miri_track_raw"), doc = "```rust")]
666 #[cfg_attr(feature = "test_miri_track_raw", doc = "```ignore")]
667 /// use abi_stable::external_types::crossbeam_channel as mpmc;
668 ///
669 /// use std::thread;
670 ///
671 /// let (tx, rx) = mpmc::bounded::<usize>(1);
672 ///
673 /// thread::spawn(move || {
674 /// for i in 0..1000 {
675 /// tx.send(i).unwrap();
676 /// }
677 /// });
678 ///
679 /// for (i, n) in rx.iter().enumerate() {
680 /// assert_eq!(i, n);
681 /// }
682 ///
683 /// ```
684 pub fn iter(&self) -> RIter<'_, T> {
685 RIter { channel: self }
686 }
687}
688
689impl<'a, T> IntoIterator for &'a RReceiver<T> {
690 type Item = T;
691 type IntoIter = RIter<'a, T>;
692
693 /// Creates an Iterator that receives values from the channel.
694 #[inline]
695 fn into_iter(self) -> RIter<'a, T> {
696 self.iter()
697 }
698}
699
700impl<T> IntoIterator for RReceiver<T> {
701 type Item = T;
702 type IntoIter = RIntoIter<T>;
703
704 /// Creates an Iterator that receives values from the channel.
705 #[inline]
706 fn into_iter(self) -> RIntoIter<T> {
707 RIntoIter { channel: self }
708 }
709}
710
711impl<T> Clone for RReceiver<T> {
712 /// Clones this channel end,getting another handle into the channel.
713 ///
714 /// Note that this allocates an RBox<_>.
715 fn clone(&self) -> Self {
716 let vtable = self.vtable();
717
718 Self {
719 channel: vtable.clone_receiver()(self.channel.as_rref()),
720 vtable: self.vtable,
721 }
722 }
723}
724
725impl<T> Debug for RReceiver<T> {
726 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
727 Debug::fmt("RReceiver{..}", f)
728 }
729}
730
731unsafe impl<T: Send> Sync for RReceiver<T> {}
732
733unsafe impl<T: Send> Send for RReceiver<T> {}
734
735impl_from_rust_repr! {
736 impl[T] From<Receiver<T>> for RReceiver<T> {
737 fn(this){
738 Self{
739 channel:ErasedReceiver::from_unerased_value(this),
740 vtable:MakeVTable::<T>::VTABLE,
741 }
742 }
743 }
744}
745
746///////////////////////////////////////////////////////////////////////////////
747
748#[inline]
749fn result_from<T, E0, E1>(res: RResult<T, E0>) -> Result<T, E1>
750where
751 E0: Into<E1>,
752{
753 match res {
754 ROk(x) => Ok(x),
755 RErr(e) => Err(e.into()),
756 }
757}
758
759#[repr(C)]
760#[derive(StableAbi)]
761struct ErasedSender<T>(PhantomData<T>, UnsafeIgnoredType<Sender<T>>);
762
763impl<T> ErasedType<'_> for ErasedSender<T> {
764 type Unerased = Sender<T>;
765}
766
767#[repr(C)]
768#[derive(StableAbi)]
769struct ErasedReceiver<T>(PhantomData<T>, UnsafeIgnoredType<Receiver<T>>);
770
771impl<T> ErasedType<'_> for ErasedReceiver<T> {
772 type Unerased = Receiver<T>;
773}
774
775///////////////////////////////////////////////////////////////////////////////
776
777#[repr(C)]
778#[derive(StableAbi)]
779#[sabi(kind(Prefix))]
780#[sabi(missing_field(panic))]
781//#[sabi(debug_print)]
782struct VTable<T> {
783 send: extern "C" fn(this: RRef<'_, ErasedSender<T>>, T) -> RResult<(), RSendError<T>>,
784 try_send: extern "C" fn(this: RRef<'_, ErasedSender<T>>, T) -> RResult<(), RTrySendError<T>>,
785 send_timeout: extern "C" fn(
786 this: RRef<'_, ErasedSender<T>>,
787 value: T,
788 timeout: RDuration,
789 ) -> RResult<(), RSendTimeoutError<T>>,
790 clone_sender: extern "C" fn(this: RRef<'_, ErasedSender<T>>) -> RBox<ErasedSender<T>>,
791 sender_is_empty: extern "C" fn(this: RRef<'_, ErasedSender<T>>) -> bool,
792 sender_is_full: extern "C" fn(this: RRef<'_, ErasedSender<T>>) -> bool,
793 sender_len: extern "C" fn(this: RRef<'_, ErasedSender<T>>) -> usize,
794 sender_capacity: extern "C" fn(this: RRef<'_, ErasedSender<T>>) -> ROption<usize>,
795
796 recv: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> RResult<T, RRecvError>,
797 try_recv: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> RResult<T, RTryRecvError>,
798 recv_timeout: extern "C" fn(
799 this: RRef<'_, ErasedReceiver<T>>,
800 timeout: RDuration,
801 ) -> RResult<T, RRecvTimeoutError>,
802 clone_receiver: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> RBox<ErasedReceiver<T>>,
803 receiver_is_empty: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> bool,
804 receiver_is_full: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> bool,
805 receiver_len: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> usize,
806 #[sabi(last_prefix_field)]
807 receiver_capacity: extern "C" fn(this: RRef<'_, ErasedReceiver<T>>) -> ROption<usize>,
808}
809
810struct MakeVTable<'a, T>(&'a T);
811
812impl<'a, T: 'a> MakeVTable<'a, T> {
813 const VALUE: VTable<T> = VTable {
814 send: ErasedSender::send,
815 try_send: ErasedSender::try_send,
816 send_timeout: ErasedSender::send_timeout,
817 clone_sender: ErasedSender::clone,
818 sender_is_empty: ErasedSender::is_empty,
819 sender_is_full: ErasedSender::is_full,
820 sender_len: ErasedSender::len,
821 sender_capacity: ErasedSender::capacity,
822
823 recv: ErasedReceiver::recv,
824 try_recv: ErasedReceiver::try_recv,
825 recv_timeout: ErasedReceiver::recv_timeout,
826 clone_receiver: ErasedReceiver::clone,
827 receiver_is_empty: ErasedReceiver::is_empty,
828 receiver_is_full: ErasedReceiver::is_full,
829 receiver_len: ErasedReceiver::len,
830 receiver_capacity: ErasedReceiver::capacity,
831 };
832
833 staticref! {
834 const WM_VALUE: WithMetadata<VTable<T>> = WithMetadata::new(Self::VALUE)
835 }
836
837 // The VTABLE for this type in this executable/library
838 const VTABLE: VTable_Ref<T> = VTable_Ref(Self::WM_VALUE.as_prefix());
839}