1use colored::Colorize;
6use std::fmt;
7
8#[allow(dead_code)]
10#[derive(Debug, Clone)]
11pub enum CliError {
20 DeviceNotFound,
22
23 MultipleDevices(Vec<String>),
25
26 InstallFailed(String),
28
29 AdbError(String),
31
32 ServiceError(String),
34
35 ResourceError(String),
37}
38
39#[allow(dead_code)]
41struct ErrorMessageBuilder {
42 title: String,
43 reasons: Vec<String>,
44 solutions: Vec<String>,
45}
46
47#[allow(dead_code)]
48impl ErrorMessageBuilder {
49 fn new(title: impl Into<String>) -> Self {
50 Self {
51 title: title.into(),
52 reasons: Vec::new(),
53 solutions: Vec::new(),
54 }
55 }
56
57 fn add_reason(mut self, reason: impl Into<String>) -> Self {
58 self.reasons.push(reason.into());
59 self
60 }
61
62 fn add_solution(mut self, solution: impl Into<String>) -> Self {
63 self.solutions.push(solution.into());
64 self
65 }
66
67 fn build(&self) -> String {
68 let mut message = self.title.clone();
69
70 if !self.reasons.is_empty() {
71 message.push_str("\n\n可能的原因:");
72 for (i, reason) in self.reasons.iter().enumerate() {
73 message.push_str(&format!("\n {}. {}", i + 1, reason));
74 }
75 }
76
77 if !self.solutions.is_empty() {
78 message.push_str("\n\n解决方案:");
79 for (i, solution) in self.solutions.iter().enumerate() {
80 message.push_str(&format!("\n {}. {}", i + 1, solution));
81 }
82 }
83
84 message
85 }
86
87 fn build_colored(&self) -> String {
88 let mut message = self.title.red().bold().to_string();
89
90 if !self.reasons.is_empty() {
91 message.push_str(&format!("\n\n{}", "可能的原因:".yellow().bold()));
92 for (i, reason) in self.reasons.iter().enumerate() {
93 message.push_str(&format!("\n {}. {}", i + 1, reason.yellow()));
94 }
95 }
96
97 if !self.solutions.is_empty() {
98 message.push_str(&format!("\n\n{}", "解决方案:".green().bold()));
99 for (i, solution) in self.solutions.iter().enumerate() {
100 message.push_str(&format!("\n {}. {}", i + 1, solution.green()));
101 }
102 }
103
104 message
105 }
106}
107
108impl CliError {
109 #[allow(dead_code)]
111 pub fn colored_message(&self) -> String {
120 match self {
121 CliError::DeviceNotFound => ErrorMessageBuilder::new("未找到连接的设备")
122 .add_reason("设备未通过 USB 连接")
123 .add_reason("ADB 服务未启动")
124 .add_reason("设备未启用 USB 调试")
125 .add_solution("检查 USB 连接")
126 .add_solution("运行 'adb devices' 确认设备可见")
127 .add_solution("在设备上启用 USB 调试模式")
128 .build_colored(),
129
130 CliError::MultipleDevices(devices) => {
131 let device_list = devices
132 .iter()
133 .map(|d| format!(" - {}", d))
134 .collect::<Vec<_>>()
135 .join("\n");
136
137 format!(
138 "{}\n\n{}\n{}\n\n{}\n{}",
139 "检测到多个设备".red().bold(),
140 "已连接的设备:".yellow().bold(),
141 device_list.yellow(),
142 "解决方案:".green().bold(),
143 format!(
144 " 使用 --serial 参数指定设备,例如: uiautomator --serial {} init",
145 devices[0]
146 )
147 .green(),
148 )
149 }
150
151 CliError::InstallFailed(reason) => {
152 ErrorMessageBuilder::new(format!("安装失败: {}", reason))
153 .add_reason("设备存储空间不足")
154 .add_reason("权限不足")
155 .add_solution("检查设备存储空间")
156 .add_solution("尝试使用 --force 选项重新安装")
157 .build_colored()
158 }
159
160 CliError::AdbError(error) => ErrorMessageBuilder::new(format!("ADB 错误: {}", error))
161 .add_reason("ADB 服务未运行")
162 .add_reason("设备连接不稳定")
163 .add_solution("重启 ADB 服务: adb kill-server && adb start-server")
164 .add_solution("重新连接设备")
165 .build_colored(),
166
167 CliError::ServiceError(error) => {
168 ErrorMessageBuilder::new(format!("服务错误: {}", error))
169 .add_reason("ATX-Agent 未正确安装")
170 .add_reason("服务启动超时")
171 .add_solution("尝试重新安装: uiautomator init --force")
172 .add_solution("检查设备日志: adb logcat | grep atx-agent")
173 .build_colored()
174 }
175
176 CliError::ResourceError(error) => {
177 ErrorMessageBuilder::new(format!("资源错误: {}", error))
178 .add_solution("请重新下载 CLI 工具或从源码重新编译")
179 .build_colored()
180 }
181 }
182 }
183}
184
185impl fmt::Display for CliError {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 let message = match self {
188 CliError::DeviceNotFound => ErrorMessageBuilder::new("未找到连接的设备")
189 .add_reason("设备未通过 USB 连接")
190 .add_reason("ADB 服务未启动")
191 .add_reason("设备未启用 USB 调试")
192 .add_solution("检查 USB 连接")
193 .add_solution("运行 'adb devices' 确认设备可见")
194 .add_solution("在设备上启用 USB 调试模式")
195 .build(),
196
197 CliError::MultipleDevices(devices) => {
198 let device_list = devices
199 .iter()
200 .map(|d| format!(" - {}", d))
201 .collect::<Vec<_>>()
202 .join("\n");
203
204 format!(
205 "检测到多个设备\n\n已连接的设备:\n{}\n\n解决方案:\n 使用 --serial 参数指定设备,例如: uiautomator --serial {} init",
206 device_list,
207 devices[0]
208 )
209 }
210
211 CliError::InstallFailed(reason) => {
212 ErrorMessageBuilder::new(format!("安装失败: {}", reason))
213 .add_reason("设备存储空间不足")
214 .add_reason("权限不足")
215 .add_solution("检查设备存储空间")
216 .add_solution("尝试使用 --force 选项重新安装")
217 .build()
218 }
219
220 CliError::AdbError(error) => ErrorMessageBuilder::new(format!("ADB 错误: {}", error))
221 .add_reason("ADB 服务未运行")
222 .add_reason("设备连接不稳定")
223 .add_solution("重启 ADB 服务: adb kill-server && adb start-server")
224 .add_solution("重新连接设备")
225 .build(),
226
227 CliError::ServiceError(error) => {
228 ErrorMessageBuilder::new(format!("服务错误: {}", error))
229 .add_reason("ATX-Agent 未正确安装")
230 .add_reason("服务启动超时")
231 .add_solution("尝试重新安装: uiautomator init --force")
232 .add_solution("检查设备日志: adb logcat | grep atx-agent")
233 .build()
234 }
235
236 CliError::ResourceError(error) => {
237 ErrorMessageBuilder::new(format!("资源错误: {}", error))
238 .add_solution("请重新下载 CLI 工具或从源码重新编译")
239 .build()
240 }
241 };
242
243 write!(f, "{}", message)
244 }
245}
246
247impl std::error::Error for CliError {}
248
249impl From<anyhow::Error> for CliError {
251 fn from(error: anyhow::Error) -> Self {
252 CliError::AdbError(error.to_string())
253 }
254}
255
256impl From<std::io::Error> for CliError {
257 fn from(error: std::io::Error) -> Self {
258 CliError::AdbError(error.to_string())
259 }
260}