libtun 0.1.0

a cross-platform(macosx, linux) tunnel library
Documentation
use async_channel;

enum Multiplex<T> {
  Msg(T),
  Close,
}

pub fn unbound<T>() -> (Writer<T>, Reader<T>) {
  let (writer, reader) = async_channel::unbounded();
  let closer = Closer::new(writer.clone());
  (Writer::new(writer.clone()), Reader::new(reader, closer))
}

pub fn closer() -> (Closer<()>, CloserReader) {
  let (writer, reader) = unbound::<()>();
  (
    Closer {
      raw: writer.raw.clone(),
    },
    CloserReader {
      raw: reader.raw,
      closer: reader.closer,
    },
  )
}

pub type CloserReader = Reader<()>;

pub struct Closer<T> {
  raw: async_channel::Sender<Multiplex<T>>,
}

impl<T> Closer<T> {
  fn new(raw: async_channel::Sender<Multiplex<T>>) -> Closer<T> {
    Closer { raw }
  }

  pub async fn close(self) {
    let _ = self.raw.send(Multiplex::Close).await;
  }
}

impl<T> Clone for Closer<T> {
  fn clone(&self) -> Closer<T> {
    Self {
      raw: self.raw.clone(),
    }
  }
}

pub struct Reader<T> {
  raw: async_channel::Receiver<Multiplex<T>>,
  closer: Closer<T>,
}

impl<T> Reader<T> {
  fn new(raw: async_channel::Receiver<Multiplex<T>>, closer: Closer<T>) -> Reader<T> {
    Reader { raw, closer }
  }

  pub async fn read(&self) -> Option<T> {
    loop {
      match self.raw.recv().await {
        Ok(item) => match item {
          Multiplex::Msg(item) => return Some(item),
          Multiplex::Close => return None,
        },
        Err(_) => return None,
      }
    }
  }

  pub fn closer(&self) -> Closer<T> {
    self.closer.clone()
  }
}

pub struct Writer<T> {
  raw: async_channel::Sender<Multiplex<T>>,
}

impl<T> Clone for Writer<T> {
  fn clone(&self) -> Writer<T> {
    Writer {
      raw: self.raw.clone(),
    }
  }
}

impl<T> Writer<T> {
  fn new(raw: async_channel::Sender<Multiplex<T>>) -> Writer<T> {
    Writer { raw }
  }

  pub async fn write(&self, t: T) -> bool {
    match self.raw.send(Multiplex::Msg(t)).await {
      Ok(_) => true,
      Err(_) => false,
    }
  }

  pub async fn close(self) {
    let closer = self.closer();
    closer.close().await;
  }

  pub fn closer(&self) -> Closer<T> {
    Closer {
      raw: self.raw.clone(),
    }
  }
}