summaryrefslogtreecommitdiffhomepage
path: root/talpid_core
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-06-12 11:14:36 +0200
committerLinus Färnstrand <linus@mullvad.net>2017-06-21 03:29:44 +0200
commit22a73df71fc6d028d84b54776d6f5e7c7066da27 (patch)
tree281bea3479beff4b45c4668690ada0d8280da637 /talpid_core
parent14e3220ec993e2be9c6f37a65710b887bae5f49e (diff)
downloadmullvadvpn-22a73df71fc6d028d84b54776d6f5e7c7066da27.tar.xz
mullvadvpn-22a73df71fc6d028d84b54776d6f5e7c7066da27.zip
Introduce plexmpsc and use in management interface
Diffstat (limited to 'talpid_core')
-rw-r--r--talpid_core/src/lib.rs3
-rw-r--r--talpid_core/src/plexmpsc.rs76
2 files changed, 79 insertions, 0 deletions
diff --git a/talpid_core/src/lib.rs b/talpid_core/src/lib.rs
index 5496d038ce..3ebb24d1ec 100644
--- a/talpid_core/src/lib.rs
+++ b/talpid_core/src/lib.rs
@@ -30,3 +30,6 @@ pub mod net;
/// Abstracts over different VPN tunnel technologies
pub mod tunnel;
+
+/// Multiplexing abstractions over `std::mpsc`
+pub mod plexmpsc;
diff --git a/talpid_core/src/plexmpsc.rs b/talpid_core/src/plexmpsc.rs
new file mode 100644
index 0000000000..be1904bdb2
--- /dev/null
+++ b/talpid_core/src/plexmpsc.rs
@@ -0,0 +1,76 @@
+use std::marker::PhantomData;
+use std::sync::mpsc;
+
+/// Abstraction over an `mpsc::Sender` that first converts the value to another type before sending.
+#[derive(Debug, Clone)]
+pub struct Sender<T, U> {
+ sender: mpsc::Sender<U>,
+ _marker: PhantomData<T>,
+}
+
+impl<T, U> Sender<T, U>
+ where T: Into<U>
+{
+ /// Converts the `T` into a `U` and sends it on the channel.
+ pub fn send(&self, t: T) -> Result<(), mpsc::SendError<U>> {
+ self.sender.send(t.into())
+ }
+}
+
+impl<T, U> From<mpsc::Sender<U>> for Sender<T, U>
+ where T: Into<U>
+{
+ fn from(sender: mpsc::Sender<U>) -> Self {
+ Sender {
+ sender: sender,
+ _marker: PhantomData,
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::sync::mpsc;
+ use std::thread;
+
+ #[derive(Debug, Eq, PartialEq)]
+ enum Inner {
+ One,
+ Two,
+ }
+
+ #[derive(Debug, Eq, PartialEq)]
+ enum Outer {
+ Inner(Inner),
+ Other,
+ }
+
+ impl From<Inner> for Outer {
+ fn from(o: Inner) -> Self {
+ Outer::Inner(o)
+ }
+ }
+
+ #[test]
+ fn sender() {
+ let (tx, rx) = mpsc::channel::<Outer>();
+ let inner_tx: Sender<Inner, Outer> = tx.clone().into();
+
+ tx.send(Outer::Other).unwrap();
+ inner_tx.send(Inner::Two).unwrap();
+
+ assert_eq!(Outer::Other, rx.recv().unwrap());
+ assert_eq!(Outer::Inner(Inner::Two), rx.recv().unwrap());
+ }
+
+ #[test]
+ fn send_between_thread() {
+ let (tx, rx) = mpsc::channel::<Outer>();
+ let inner_tx: Sender<Inner, Outer> = tx.clone().into();
+
+ thread::spawn(move || { inner_tx.send(Inner::One).unwrap(); });
+
+ assert_eq!(Outer::Inner(Inner::One), rx.recv().unwrap());
+ }
+}