You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

merged.rs 4.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //! Merge external stream into an [`EventStream`][super::EventStream].
  2. //!
  3. //! Sometimes nodes need to listen to external events, in addition to Dora events.
  4. //! This module provides support for that by providing the [`MergeExternal`] trait.
  5. use futures::{Stream, StreamExt};
  6. use futures_concurrency::stream::Merge;
  7. /// A Dora event or an event from an external source.
  8. #[derive(Debug)]
  9. #[allow(clippy::large_enum_variant)]
  10. pub enum MergedEvent<E> {
  11. /// A Dora event
  12. Dora(super::Event),
  13. /// An external event
  14. ///
  15. /// Yielded by the stream that was merged into the Dora [`EventStream`][super::EventStream].
  16. External(E),
  17. }
  18. /// A general enum to represent a value of two possible types.
  19. pub enum Either<A, B> {
  20. /// Value is of the first type, type `A`.
  21. First(A),
  22. /// Value is of the second type, type `B`.
  23. Second(B),
  24. }
  25. impl<A> Either<A, A> {
  26. /// Unwraps an `Either` instance where both types are identical.
  27. pub fn flatten(self) -> A {
  28. match self {
  29. Either::First(a) => a,
  30. Either::Second(a) => a,
  31. }
  32. }
  33. }
  34. /// Allows merging an external event stream into an existing event stream.
  35. // TODO: use impl trait return type once stable
  36. pub trait MergeExternal<'a, E> {
  37. /// The item type yielded from the merged stream.
  38. type Item;
  39. /// Merge the given stream into an existing event stream.
  40. ///
  41. /// Returns a new event stream that yields items from both streams.
  42. /// The ordering between the two streams is not guaranteed.
  43. fn merge_external(
  44. self,
  45. external_events: impl Stream<Item = E> + Unpin + 'a,
  46. ) -> Box<dyn Stream<Item = Self::Item> + Unpin + 'a>;
  47. }
  48. /// Allows merging a sendable external event stream into an existing (sendable) event stream.
  49. ///
  50. /// By implementing [`Send`], the streams can be sent to different threads.
  51. pub trait MergeExternalSend<'a, E> {
  52. /// The item type yielded from the merged stream.
  53. type Item;
  54. /// Merge the given stream into an existing event stream.
  55. ///
  56. /// Returns a new event stream that yields items from both streams.
  57. /// The ordering between the two streams is not guaranteed.
  58. fn merge_external_send(
  59. self,
  60. external_events: impl Stream<Item = E> + Unpin + Send + Sync + 'a,
  61. ) -> Box<dyn Stream<Item = Self::Item> + Unpin + Send + Sync + 'a>;
  62. }
  63. impl<'a, E> MergeExternal<'a, E> for super::EventStream
  64. where
  65. E: 'static,
  66. {
  67. type Item = MergedEvent<E>;
  68. fn merge_external(
  69. self,
  70. external_events: impl Stream<Item = E> + Unpin + 'a,
  71. ) -> Box<dyn Stream<Item = Self::Item> + Unpin + 'a> {
  72. let dora = self.map(MergedEvent::Dora);
  73. let external = external_events.map(MergedEvent::External);
  74. Box::new((dora, external).merge())
  75. }
  76. }
  77. impl<'a, E> MergeExternalSend<'a, E> for super::EventStream
  78. where
  79. E: 'static,
  80. {
  81. type Item = MergedEvent<E>;
  82. fn merge_external_send(
  83. self,
  84. external_events: impl Stream<Item = E> + Unpin + Send + Sync + 'a,
  85. ) -> Box<dyn Stream<Item = Self::Item> + Unpin + Send + Sync + 'a> {
  86. let dora = self.map(MergedEvent::Dora);
  87. let external = external_events.map(MergedEvent::External);
  88. Box::new((dora, external).merge())
  89. }
  90. }
  91. impl<'a, E, F, S> MergeExternal<'a, F> for S
  92. where
  93. S: Stream<Item = MergedEvent<E>> + Unpin + 'a,
  94. E: 'a,
  95. F: 'a,
  96. {
  97. type Item = MergedEvent<Either<E, F>>;
  98. fn merge_external(
  99. self,
  100. external_events: impl Stream<Item = F> + Unpin + 'a,
  101. ) -> Box<dyn Stream<Item = Self::Item> + Unpin + 'a> {
  102. let first = self.map(|e| match e {
  103. MergedEvent::Dora(d) => MergedEvent::Dora(d),
  104. MergedEvent::External(e) => MergedEvent::External(Either::First(e)),
  105. });
  106. let second = external_events.map(|e| MergedEvent::External(Either::Second(e)));
  107. Box::new((first, second).merge())
  108. }
  109. }
  110. impl<'a, E, F, S> MergeExternalSend<'a, F> for S
  111. where
  112. S: Stream<Item = MergedEvent<E>> + Unpin + Send + Sync + 'a,
  113. E: 'a,
  114. F: 'a,
  115. {
  116. type Item = MergedEvent<Either<E, F>>;
  117. fn merge_external_send(
  118. self,
  119. external_events: impl Stream<Item = F> + Unpin + Send + Sync + 'a,
  120. ) -> Box<dyn Stream<Item = Self::Item> + Unpin + Send + Sync + 'a> {
  121. let first = self.map(|e| match e {
  122. MergedEvent::Dora(d) => MergedEvent::Dora(d),
  123. MergedEvent::External(e) => MergedEvent::External(Either::First(e)),
  124. });
  125. let second = external_events.map(|e| MergedEvent::External(Either::Second(e)));
  126. Box::new((first, second).merge())
  127. }
  128. }