Skip to main content

computer_use/
error.rs

1use std::fmt;
2
3/// Convenience alias used throughout the crate.
4pub type Result<T, E = Error> = std::result::Result<T, E>;
5
6/// An OS permission that computer use depends on.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum Permission {
10    /// Reading and driving other apps through the accessibility API.
11    Accessibility,
12    /// Capturing pixels of other apps' windows.
13    ScreenRecording,
14}
15
16impl fmt::Display for Permission {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.write_str(match self {
19            Self::Accessibility => "accessibility",
20            Self::ScreenRecording => "screen recording",
21        })
22    }
23}
24
25/// Everything that can go wrong while observing or driving an app.
26#[derive(Debug, thiserror::Error)]
27#[non_exhaustive]
28pub enum Error {
29    /// No running or installed app matched the query.
30    #[error("app not found: {0}")]
31    AppNotFound(String),
32
33    /// The app is running but has no window that can be observed.
34    #[error("no usable window for app {0}")]
35    WindowNotFound(String),
36
37    /// An action referenced app state that was never captured (or was discarded).
38    #[error("no app state for {0}; call get_app_state first")]
39    NoAppState(String),
40
41    /// An element index did not exist in the latest captured state.
42    #[error("element {index} not found in the latest state of {app}")]
43    ElementNotFound {
44        /// App the lookup was made against.
45        app: String,
46        /// The requested element index.
47        index: usize,
48    },
49
50    /// A caller-supplied argument was invalid.
51    #[error("invalid argument: {0}")]
52    InvalidArgument(String),
53
54    /// A required OS permission has not been granted to this process.
55    #[error("{0} permission has not been granted to this process")]
56    PermissionDenied(Permission),
57
58    /// The operation is not available on this platform or backend.
59    #[error("unsupported: {0}")]
60    Unsupported(String),
61
62    /// The platform accepted the request but reported that it failed.
63    #[error("action failed: {0}")]
64    ActionFailed(String),
65
66    /// The state the action needs is missing (for example, no screenshot was captured).
67    #[error("state unavailable: {0}")]
68    StateUnavailable(String),
69
70    /// A platform API returned an unexpected error.
71    #[error("platform error: {0}")]
72    Platform(String),
73
74    /// Encoding a screenshot failed.
75    #[error("image encoding failed: {0}")]
76    Image(#[from] image::ImageError),
77
78    /// An I/O error, for example while launching an app.
79    #[error(transparent)]
80    Io(#[from] std::io::Error),
81}
82
83impl Error {
84    pub(crate) fn invalid(message: impl Into<String>) -> Self {
85        Self::InvalidArgument(message.into())
86    }
87
88    #[cfg_attr(not(target_os = "macos"), allow(dead_code))]
89    pub(crate) fn platform(message: impl Into<String>) -> Self {
90        Self::Platform(message.into())
91    }
92
93    pub(crate) fn action(message: impl Into<String>) -> Self {
94        Self::ActionFailed(message.into())
95    }
96}