taptap 0.1.1

An implementation of the Tigo TAP protocol
Documentation
use serialport::Result;
use serialport::{
    available_ports, DataBits, FlowControl, Parity, SerialPort, SerialPortInfo, SerialPortType,
    StopBits,
};
use std::time::Duration;

#[derive(Debug, Clone)]
pub struct PortInfo(SerialPortInfo);

impl PortInfo {
    pub fn list() -> Result<Vec<PortInfo>> {
        available_ports().map(|vec| vec.into_iter().map(Self).collect())
    }

    pub fn open(&self) -> Result<Port> {
        Port::open(&self.0.port_name)
    }

    pub fn name(&self) -> &str {
        &self.0.port_name
    }

    pub fn port_type(&self) -> &SerialPortType {
        &self.0.port_type
    }
}

#[derive(Debug)]
pub struct Port {
    pub inner: Box<dyn SerialPort>,
}

impl Port {
    pub fn open(name: &str) -> Result<Self> {
        serialport::new(name, 38400)
            .data_bits(DataBits::Eight)
            .parity(Parity::None)
            .stop_bits(StopBits::One)
            .flow_control(FlowControl::None)
            .timeout(Duration::from_millis(5))
            .open()
            .map(Port::new)
    }

    fn new(inner: Box<dyn SerialPort>) -> Self {
        Port { inner }
    }
}

impl std::io::Read for Port {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        loop {
            match self.inner.read(buf) {
                Ok(n) => return Ok(n),
                Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
                    continue;
                }
                Err(e) => return Err(e),
            }
        }
    }
}

impl std::io::Write for Port {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.inner.write(buf)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.inner.flush()
    }
}

impl super::Connection for Port {}