Skip to main content

adbutils/
errors.rs

1//! Error types. Port of `adbutils/errors.py`.
2
3use std::sync::LazyLock;
4
5use regex::Regex;
6
7/// Result alias used throughout the crate.
8pub type Result<T> = std::result::Result<T, AdbError>;
9
10/// All adb errors. Mirrors the Python exception hierarchy, which is flat under
11/// `AdbError`; here the variants distinguish the former subclasses.
12#[derive(Debug, thiserror::Error)]
13pub enum AdbError {
14    /// Generic adb error carrying the server-reported message (`AdbError`).
15    #[error("{0}")]
16    Adb(String),
17
18    /// Timeout communicating with the adb server (`AdbTimeout`).
19    #[error("adb timeout: {0}")]
20    Timeout(String),
21
22    /// Connection error talking to the adb server (`AdbConnectionError`).
23    #[error("adb connection error: {0}")]
24    Connection(String),
25
26    /// APK install failure (`AdbInstallError`). `reason` is parsed from the
27    /// `Failure [REASON]` marker in the `pm install` output.
28    #[error("{output}")]
29    Install { reason: String, output: String },
30
31    /// Sync sub-protocol error (`AdbSyncError`).
32    #[error("adb sync error: {0}")]
33    Sync(String),
34
35    /// Underlying IO error.
36    #[error(transparent)]
37    Io(#[from] std::io::Error),
38}
39
40impl AdbError {
41    /// Build an [`AdbError::Adb`] from anything stringy.
42    pub fn adb(msg: impl Into<String>) -> Self {
43        AdbError::Adb(msg.into())
44    }
45
46    /// Parse `pm install` output into an [`AdbError::Install`], extracting the
47    /// bracketed reason from a `Failure [REASON]` line (default `"Unknown"`).
48    /// Mirrors `AdbInstallError.__init__` (`errors.py:24`).
49    pub fn install(output: impl Into<String>) -> Self {
50        static RE: LazyLock<Regex> =
51            LazyLock::new(|| Regex::new(r"Failure \[([A-Z_]+).*\]").unwrap());
52        let output = output.into();
53        let reason = RE
54            .captures(&output)
55            .and_then(|c| c.get(1))
56            .map(|m| m.as_str().to_string())
57            .unwrap_or_else(|| "Unknown".to_string());
58        AdbError::Install { reason, output }
59    }
60}