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
use std::process::{ExitStatus, Output};
/// Error that is returned when the CLI does not successfully complete a
/// request, or when the library encountered a problem while generating the
/// request or while interpreting its response.
#[derive(Debug)]
pub enum Error {
/// This error is returned when the CLI exits with a non-zero exit code.
Output {
/// Contains the output written to stdout before the CLI exited with a
/// non-zero exit code.
stdout: String,
/// Contains the output written to stderr before the CLI exited with a
/// non-zero exit code.
stderr: String,
/// Contains the exit status.
status: ExitStatus,
},
/// This error is returned when the library failed spawning a new process
/// that runs the CLI. Most likely, this is caused by an incorrect Xcode
/// path. If the Xcode path was set automatically, Xcode is probably not
/// installed. If the Xcode path was set manually, it's probably incorrect.
/// Make sure that it ends with `Xcode(-*).app` (where * can be an optional
/// suffix to distinguish between stable and beta).
Io(std::io::Error),
/// This error is returned when the library failed to deserialize the
/// response of `simctl list -j` (in [`crate::list`]) or when it failed to
/// serialize a request for `simctl push` (in [`crate::push`]).
Json(serde_json::Error),
/// This error is returned when the library failed to interpret the CLI's
/// response as a UTF-8 encoded string.
Utf8(std::string::FromUtf8Error),
}
impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
Error::Io(error)
}
}
impl From<serde_json::Error> for Error {
fn from(error: serde_json::Error) -> Self {
Error::Json(error)
}
}
impl From<std::string::FromUtf8Error> for Error {
fn from(error: std::string::FromUtf8Error) -> Self {
Error::Utf8(error)
}
}
/// Partial application of the standard `Result` type, with the simctl [`Error`]
/// pre-applied.
pub type Result<T> = std::result::Result<T, Error>;
pub trait Validate {
fn validate(self) -> Result<()>;
fn validate_with_output(self) -> Result<Output>;
}
impl Validate for Output {
fn validate(self) -> Result<()> {
let _ = self.validate_with_output()?;
Ok(())
}
fn validate_with_output(self) -> Result<Output> {
match self.status.success() {
true => Ok(self),
false => Err(Error::Output {
stdout: String::from_utf8(self.stdout).unwrap(),
stderr: String::from_utf8(self.stderr).unwrap(),
status: self.status,
}),
}
}
}