1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use std::path::Path;

use tokio::io::{AsyncBufReadExt, BufReader}; // 确保导入所需的trait
use tokio::process::Command;

/// ADBCmd allows you to execute adb commands asynchronously.
#[derive(Debug, Clone)]
pub struct ADBCmd {
    cmd: String,
    is_shell: bool,
}
impl ADBCmd {
    pub fn new(cmd: String, is_shell: bool) -> Self {
        ADBCmd { cmd, is_shell }
    }
    pub fn create_cmd(self) -> Command {
        let mut command = Command::new(self.cmd);
        if self.is_shell {
            command.arg("shell");
        }
        command
    }
    // run_async runs the given adb command asynchronously.
    /// ```no_run
    ///
    /// use std::process::Command;
    ///
    /// use ADB::cmd::ADBCmd;
    ///
    /// let adb_cmd = ADBCmd::new();
    /// #[tokio::main]
    /// adb_cmd.run_async(vec!["devices".to_string()], |line| {
    ///     println!("{}", line);
    ///     line
    /// }).await;
    /// ```
    pub async fn run_async<F>(&self, args: Vec<String>, mut fnc: F)
    where
        F: FnMut(String) -> String + 'static,
    {
        let mut cmd = <ADBCmd as Clone>::clone(&self)
            .create_cmd()
            .args(args)
            .stdout(std::process::Stdio::piped()) // 将标准输出重定向到管道
            .spawn() // 启动子进程
            .expect("failed to execute command");

        if let Some(stdout) = cmd.stdout.take() {
            let reader = BufReader::new(stdout);
            let mut lines = reader.lines();

            while let Ok(Some(line)) = lines.next_line().await {
                let _result = fnc(line);
                // 这里你可以直接使用 `result`,或者根据需要做进一步的处理
            }
        }
    }
    // run runs the given adb command synchronously.

    /// ```no_run
    /// use std::process::Command;
    ///
    /// use ADB::cmd::ADBCmd;
    ///
    /// let adb_cmd = ADBCmd::new();
    ///
    /// let result = adb_cmd.run(vec!["devices".to_string()]);
    /// ```
    pub async fn run(&self, args: Vec<String>) -> Result<String, String> {
        // let output = std::process::Command::new(self.cmd).args(args).output();
        let output = <ADBCmd as Clone>::clone(&self)
            .create_cmd()
            .args(args)
            .output();
        match output.await {
            Ok(child) => {
                if child.status.success() {
                    let stdout = String::from_utf8_lossy(&child.stdout).to_string();
                    Ok(stdout)
                } else {
                    let stderr = String::from_utf8_lossy(&child.stderr).to_string();
                    Err(stderr)
                }
            }
            Err(err) => {
                let err_str = format!("Failed to execute Adb command: {}", err) as String;
                Err(err_str)
            }
        }
    }

    /// Get variable on command

    /// ```no_run
    ///  let mut arg=String::from("mmi");
    ///  let exec_args=vec![];
    ///  let args= vec![
    ///     "ls".to_string(),
    ///     "/system/bin/sxrmmi".to_string()
    ///     ]
    ///  let _prefix= ADBCmd::new("adb",false).get_var_arg(args);
    ///  if _prefix.is_ok(){
    ///      arg = format!("{}{}","sxr".to_string(),arg);
    ///  }else{
    ///      arg = format!("{}{}","ssnwt".to_string(),arg);
    ///  }
    ///  exec_args.push(arg);
    ///  exec_args.push("stop".to_string());
    ///  let res= ADBCmd::new("adb",false).run(exec_args);
    ///  
    /// ```
    pub async fn get_var_arg(self, args: Vec<String>) -> bool {
        let res = self.run(args).await;
        match res {
            Ok(_) => true,
            Err(_) => false,
        }
    }
    /// 获取文件路径
    /// ```no_run
    ///  let res= ADBCmd::new("adb",false).get_file_path("./resources/file.xml");
    /// ```
    pub fn get_file_path(path: &str) -> Result<String, String> {
        let mut _custom_path = Path::new(path).canonicalize();
        match _custom_path {
            Ok(p) => Ok(p.as_os_str().to_string_lossy().to_string()),
            Err(_err) => Err(format!("The file path does not exist or is incorrect")),
        }
    }
}