simctl/
error.rs

1use std::process::{ExitStatus, Output};
2
3/// Error that is returned when the CLI does not successfully complete a
4/// request, or when the library encountered a problem while generating the
5/// request or while interpreting its response.
6#[derive(Debug)]
7pub enum Error {
8    /// This error is returned when the CLI exits with a non-zero exit code.
9    Output {
10        /// Contains the output written to stdout before the CLI exited with a
11        /// non-zero exit code.
12        stdout: String,
13
14        /// Contains the output written to stderr before the CLI exited with a
15        /// non-zero exit code.
16        stderr: String,
17
18        /// Contains the exit status.
19        status: ExitStatus,
20    },
21
22    /// This error is returned when the library failed spawning a new process
23    /// that runs the CLI. Most likely, this is caused by an incorrect Xcode
24    /// path. If the Xcode path was set automatically, Xcode is probably not
25    /// installed. If the Xcode path was set manually, it's probably incorrect.
26    /// Make sure that it ends with `Xcode(-*).app` (where * can be an optional
27    /// suffix to distinguish between stable and beta).
28    Io(std::io::Error),
29
30    /// This error is returned when the library failed to deserialize the
31    /// response of `simctl list -j` (in [`crate::list`]) or when it failed to
32    /// serialize a request for `simctl push` (in [`crate::push`]).
33    Json(serde_json::Error),
34
35    /// This error is returned when the library failed to interpret the CLI's
36    /// response as a UTF-8 encoded string.
37    Utf8(std::string::FromUtf8Error),
38}
39
40impl From<std::io::Error> for Error {
41    fn from(error: std::io::Error) -> Self {
42        Error::Io(error)
43    }
44}
45
46impl From<serde_json::Error> for Error {
47    fn from(error: serde_json::Error) -> Self {
48        Error::Json(error)
49    }
50}
51
52impl From<std::string::FromUtf8Error> for Error {
53    fn from(error: std::string::FromUtf8Error) -> Self {
54        Error::Utf8(error)
55    }
56}
57
58/// Partial application of the standard `Result` type, with the simctl [`Error`]
59/// pre-applied.
60pub type Result<T> = std::result::Result<T, Error>;
61
62pub trait Validate {
63    fn validate(self) -> Result<()>;
64    fn validate_with_output(self) -> Result<Output>;
65}
66
67impl Validate for Output {
68    fn validate(self) -> Result<()> {
69        let _ = self.validate_with_output()?;
70        Ok(())
71    }
72
73    fn validate_with_output(self) -> Result<Output> {
74        match self.status.success() {
75            true => Ok(self),
76            false => Err(Error::Output {
77                stdout: String::from_utf8(self.stdout).unwrap(),
78                stderr: String::from_utf8(self.stderr).unwrap(),
79                status: self.status,
80            }),
81        }
82    }
83}