adb_client/emulator_device/
adb_emulator_device.rs

1use std::{
2    net::{Ipv4Addr, SocketAddrV4},
3    sync::LazyLock,
4};
5
6use crate::{ADBServerDevice, ADBTransport, Result, RustADBError, TCPEmulatorTransport};
7use regex::Regex;
8
9static EMULATOR_REGEX: LazyLock<Regex> = LazyLock::new(|| {
10    Regex::new("^emulator-(?P<port>\\d+)$").expect("wrong syntax for emulator regex")
11});
12
13/// Represents an emulator connected to the ADB server.
14#[derive(Debug)]
15pub struct ADBEmulatorDevice {
16    /// Unique device identifier.
17    pub identifier: String,
18    /// Internal [TCPEmulatorTransport]
19    transport: TCPEmulatorTransport,
20}
21
22impl ADBEmulatorDevice {
23    /// Instantiates a new [ADBEmulatorDevice]
24    pub fn new(identifier: String, ip_address: Option<Ipv4Addr>) -> Result<Self> {
25        let ip_address = match ip_address {
26            Some(ip_address) => ip_address,
27            None => Ipv4Addr::new(127, 0, 0, 1),
28        };
29
30        let groups = EMULATOR_REGEX
31            .captures(&identifier)
32            .ok_or(RustADBError::DeviceNotFound(format!(
33                "Device {identifier} is likely not an emulator"
34            )))?;
35
36        let port = groups
37            .name("port")
38            .ok_or(RustADBError::RegexParsingError)?
39            .as_str()
40            .parse::<u16>()?;
41
42        let socket_addr = SocketAddrV4::new(ip_address, port);
43
44        let transport = TCPEmulatorTransport::new(socket_addr);
45        Ok(Self {
46            identifier,
47            transport,
48        })
49    }
50
51    pub(crate) fn get_transport_mut(&mut self) -> &mut TCPEmulatorTransport {
52        &mut self.transport
53    }
54
55    /// Connect to underlying transport
56    pub(crate) fn connect(&mut self) -> Result<&mut TCPEmulatorTransport> {
57        self.transport.connect()?;
58
59        Ok(self.get_transport_mut())
60    }
61}
62
63impl TryFrom<ADBServerDevice> for ADBEmulatorDevice {
64    type Error = RustADBError;
65
66    fn try_from(value: ADBServerDevice) -> std::result::Result<Self, Self::Error> {
67        match &value.identifier {
68            Some(device_identifier) => ADBEmulatorDevice::new(
69                device_identifier.clone(),
70                Some(*value.transport.get_socketaddr().ip()),
71            ),
72            None => Err(RustADBError::DeviceNotFound(
73                "cannot connect to an emulator device without knowing its identifier".to_string(),
74            )),
75        }
76    }
77}
78
79impl Drop for ADBEmulatorDevice {
80    fn drop(&mut self) {
81        // Best effort here
82        let _ = self.transport.disconnect();
83    }
84}