apple_clis/ios_deploy/
detect.rs1use super::IosDeployCLIInstance;
2use crate::prelude::*;
3
4impl IosDeployCLIInstance {
5 #[instrument(ret, skip_all)]
6 pub fn detect_devices(&self, config: &DetectDevicesConfig) -> Result<Vec<Device>> {
7 let mut command = self
8 .bossy_command()
9 .with_arg("--detect")
10 .with_arg("--json")
11 .with_args(["--timeout", config.timeout.to_string().as_str()]);
12
13 if !config.wifi {
14 command.add_arg("--no-wifi");
15 }
16
17 let output = match command.run_and_wait_for_string() {
18 Ok(output) => output,
19 Err(err) => {
20 if err.status().and_then(|s| s.code()) == Some(253) {
21 info!(exit_status = ?err.status(), "No devices detected, since ios-deploy exited with status code 253");
22 return Ok(vec![]);
23 }
24 Err(err)?
25 }
26 };
27
28 trace!(previous_output = %output, "Before processing ios-deploy JSON output");
29
30 let output = format!("[{}]", output);
33 let output = output.replace("}{", "},{");
34
35 trace!(after_output = %output, "After processing ios-deploy JSON output");
36
37 #[derive(Debug, Deserialize)]
38 struct Event {
39 #[serde(rename(deserialize = "Interface"))]
40 interface: DeviceInterface,
41
42 #[serde(rename(deserialize = "Device"))]
43 device: DeviceDetected,
44 }
45
46 #[derive(Debug, Deserialize)]
47 struct DeviceDetected {
48 #[serde(rename(deserialize = "DeviceIdentifier"))]
49 device_identifier: String,
50
51 #[serde(rename(deserialize = "DeviceName"))]
52 device_name: String,
53
54 #[serde(rename(deserialize = "modelName"))]
55 model_name: ModelName,
56 }
57
58 let events = match serde_json::from_str::<Vec<Event>>(&output) {
59 Ok(events) => events,
60 Err(err) => {
61 error!(%output, "Failed to parse JSON output from ios-deploy");
62 Err(err)?
63 }
64 };
65 let devices = events
66 .into_iter()
67 .map(|event| Device {
68 device_name: event.device.device_name,
69 device_identifier: event.device.device_identifier,
70 model_name: event.device.model_name,
71 interface: event.interface,
72 })
73 .collect();
74
75 Ok(devices)
76 }
77}
78
79#[derive(Debug)]
80#[cfg_attr(feature = "cli", derive(clap::Args))]
81pub struct DetectDevicesConfig {
82 #[cfg_attr(feature = "cli", clap(long, default_value_t = 1))]
83 pub timeout: u8,
84
85 #[cfg_attr(feature = "cli", clap(long, default_value_t = false))]
86 pub wifi: bool,
87}
88
89impl Default for DetectDevicesConfig {
90 #[instrument(level = "trace", skip())]
91 fn default() -> Self {
92 DetectDevicesConfig {
93 timeout: 1,
94 wifi: true,
95 }
96 }
97}
98
99#[derive(Debug, Serialize, Deserialize)]
100pub struct Device {
101 pub device_identifier: String,
102 pub device_name: String,
103 pub model_name: ModelName,
104 pub interface: DeviceInterface,
105}
106
107#[derive(Debug, Serialize, Deserialize)]
108#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
109pub enum DeviceInterface {
110 Usb,
111 Wifi,
112}