radb_client 1.3.0

adb client for rust
Documentation
use std::ffi::OsString;
use std::fmt::{Debug, Display, Formatter};
use std::net::{AddrParseError, SocketAddr};
use std::str::FromStr;
use std::vec::IntoIter;

use crate::error::Error;
use crate::traits::AsArgs;
use crate::types::ConnectionType;

#[allow(dead_code)]
impl ConnectionType {
    fn values(&self) -> Vec<OsString> {
        match self {
            ConnectionType::TcpIp(sock) => vec!["-s".into(), sock.to_string().into()],
            ConnectionType::Transport(id) => vec!["-t".into(), id.to_string().into()],
            ConnectionType::USB => vec!["-d".into()],
        }
    }

    pub fn from_socket_addr<I: Into<SocketAddr>>(socket_addr: I) -> Self {
        ConnectionType::TcpIp(socket_addr.into())
    }

    pub fn try_from_ip(value: &str) -> crate::result::Result<ConnectionType> {
        Ok(ConnectionType::TcpIp(value.parse()?))
    }
}

impl AsArgs<OsString> for ConnectionType {
    fn as_args(&self) -> Vec<OsString> {
        self.values()
    }
}

impl Display for ConnectionType {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ConnectionType::TcpIp(sock) => write!(f, "ip:{sock}"),
            ConnectionType::Transport(id) => write!(f, "transport_id:{id}"),
            ConnectionType::USB => write!(f, "usb"),
        }
    }
}

impl Debug for ConnectionType {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let mut debug = f.debug_struct("AddressType");
        match self {
            ConnectionType::TcpIp(sock) => debug.field("ip", sock),
            ConnectionType::Transport(id) => debug.field("transport_id", id),
            ConnectionType::USB => debug.field("usb", &""),
        };
        debug.finish()
    }
}

impl From<SocketAddr> for ConnectionType {
    fn from(value: SocketAddr) -> Self {
        ConnectionType::from_socket_addr(value)
    }
}

impl FromStr for ConnectionType {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let addr: Result<SocketAddr, AddrParseError> = s.parse();
        match addr {
            Ok(addr) => Ok(ConnectionType::TcpIp(addr)),
            Err(_err) => Err(Error::AddressParseError),
        }
    }
}

impl TryFrom<&str> for ConnectionType {
    type Error = Error;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Self::from_str(value)
    }
}

impl IntoIterator for ConnectionType {
    type Item = OsString;
    type IntoIter = IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.as_args().into_iter()
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
    use std::str::FromStr;

    use crate::test::test::init_log;
    use simple_cmd::debug::CommandDebug;

    use crate::types::ConnectionType;

    #[test]
    fn test_parse_address() {
        let ip = "192.168.1.34:5555";
        let sock_addr = ip
            .parse::<SocketAddr>()
            .expect("failed to parse ip address");
        let _address: ConnectionType = ConnectionType::from_socket_addr(sock_addr);
        let _address: ConnectionType =
            ConnectionType::try_from_ip(ip).expect("failed to parse ip address");
        let _address: ConnectionType = ip.parse().unwrap();
        let _address = ConnectionType::from(sock_addr);
        let _address = ConnectionType::from_str(ip);

        ConnectionType::from_str("invalid").expect_err("Expected error");
    }

    #[test]
    fn test_display() {
        assert_eq!("usb", ConnectionType::USB.to_string());
        assert_eq!("transport_id:4", ConnectionType::Transport(4).to_string());
        assert_eq!(
            "ip:192.168.1.1:5555",
            ConnectionType::TcpIp("192.168.1.1:5555".parse().unwrap()).to_string()
        );
    }

    #[test]
    fn test_debug() {
        let addr = format!("{:#?}", ConnectionType::USB);
        println!("{addr}");
        assert_eq!("AddressType {\n    usb: \"\",\n}", addr);

        let addr = format!("{:#?}", ConnectionType::Transport(4));
        println!("{addr}");
        assert_eq!("AddressType {\n    transport_id: 4,\n}", addr);

        let addr = format!(
            "{:#?}",
            ConnectionType::TcpIp("192.168.1.1:5555".parse().unwrap())
        );
        println!("{addr}");
        assert_eq!("AddressType {\n    ip: 192.168.1.1:5555,\n}", addr);
    }

    #[test]
    fn test_copy() {
        let addr = ConnectionType::USB;
        let addr2 = addr.clone();
        assert_eq!(addr, addr2);

        let addr = ConnectionType::Transport(4);
        let addr2 = addr.clone();
        assert_eq!(addr, addr2);

        let addr = ConnectionType::try_from("192.168.1.1:5555").unwrap();
        let addr2 = addr.clone();
        assert_eq!(addr, addr2);
    }

    #[test]
    fn test_args() {
        init_log();
        let addr = ConnectionType::USB;
        let mut builder = std::process::Command::new("adb");
        let cmd = builder.args(addr).arg("get-state").debug();
        let output = cmd.output();
        println!("output: {output:?}");

        let addr = ConnectionType::Transport(4);
        let mut builder = std::process::Command::new("adb");
        let cmd = builder.args(addr).arg("get-state").debug();
        let output = cmd.output();
        println!("output: {output:?}");

        let addr = ConnectionType::TcpIp(SocketAddr::V4(SocketAddrV4::new(
            Ipv4Addr::new(192, 168, 1, 34),
            5555,
        )));
        let mut builder = std::process::Command::new("adb");
        let cmd = builder.args(addr).arg("get-state").debug();
        let output = cmd.output();
        println!("output: {output:?}");
    }
}