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}