use thiserror::Error;
#[derive(Error, Debug)]
#[error("failed to use fdfe ({0})")]
pub struct GoogleError(pub String);
#[derive(Error, Debug)]
pub enum PropParseError {
#[error("failed to parse ini ({0})")]
InvalidIni(#[from] ini::ParseError),
}
#[derive(Error, Debug)]
pub enum GenericRequestError {
#[error("failed to parse URL ({0})")]
BadUri(#[from] url::ParseError),
#[error("bad header name ({0})")]
BadHeaderName(#[from] http::header::InvalidHeaderName),
#[error("bad header value ({0})")]
BadHeaderValue(#[from] http::header::InvalidHeaderValue),
#[error("google returned an invalid response ({0})")]
BadResponseProto(#[from] prost::DecodeError),
#[error("failed to fetch resource ({0})")]
HttpError(#[from] reqwest::Error),
}
#[derive(Error, Debug)]
pub enum FetchAasError {
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
}
#[derive(Error, Debug)]
pub enum CheckinError {
#[error("system clock went back in time ({0})")]
InvalidSystemTime(#[from] std::time::SystemTimeError),
#[error("no build was provided for device props")]
NoBuild(),
#[error("no device string was provided for device props")]
NoDevice(),
#[error("google returned an invalid response ({0})!")]
BadResponse(#[from] prost::DecodeError),
#[error("props error ({0})")]
Props(#[from] PropsError),
#[error("failed to fetch resource ({0})")]
HttpError(#[from] reqwest::Error),
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum LoginError {
#[error("checkin failed ({0})")]
Checkin(#[from] CheckinError),
#[error("upload device config failed ({0})")]
Upload(#[from] UploadDeviceError),
#[error("auth fetch failed ({0})")]
Auth(#[from] FetchAuthError),
#[error("TOC fetch / TOS accept failed ({0})")]
Toc(#[from] TocError),
#[error("google returned no 'device_checkin_consistency_token'")]
NoDeviceToken(),
#[error("google returned no 'android_id'")]
NoAndroidId(),
#[error("google returned no 'upload_device_config_token'")]
NoConfigToken(),
}
#[derive(Error, Debug)]
pub enum UploadDeviceError {
#[error("props error ({0})")]
Props(#[from] PropsError),
#[error("google returned an invalid response")]
InvalidResponse(#[from] prost::DecodeError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum FetchAuthError {
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("google returned no expire time")]
NoExpireTime(),
#[error("google returned invalid expire time ({0})")]
InvalidExpireTime(#[from] std::num::ParseIntError),
#[error("props error ({0})")]
Props(#[from] PropsError),
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum PropsError {
#[error("failed to renew auth token ({0})")]
UpdateAuth(#[from] Box<FetchAuthError>),
#[error("no props were provided")]
NoProps(),
#[error("no build was provided")]
NoBuild(),
#[error("no build sdk version was provided")]
NoBuildSDK(),
#[error("no build device was provided")]
NoBuildDevice(),
#[error("no build model was provided")]
NoBuildModel(),
#[error("no build product was provided")]
NoBuildProduct(),
#[error("no 'Vending.versionString' was provided")]
NoVersionString(),
#[error("no 'Build.VERSION.RELEASE' was provided")]
NoVersionRelease(),
#[error("no 'Vending.version' was provided")]
NoVersion(),
#[error("no 'Build.ID' was provided")]
NoBuildId(),
#[error("no 'SimOperator' was provided")]
NoSimOperator(),
}
#[derive(Error, Debug)]
pub enum TocError {
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
#[error("props error ({0})")]
Props(#[from] PropsError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("google returned an invalid response ({0})")]
InvalidResponse(#[from] prost::DecodeError),
}
#[derive(Error, Debug)]
pub enum DetailsError {
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("props error ({0})")]
Props(#[from] PropsError),
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum DownloadsError {
#[error("fetching latest version failed ({0})")]
VersionFetchError(#[from] DetailsError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("header error ({0})")]
Props(#[from] PropsError),
#[error("request failed ({0})")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum CategoryError {
#[error("header error ({0})")]
Props(#[from] PropsError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("Got request error {0}!")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum SearchSuggestionError {
#[error("header error ({0})")]
Props(#[from] PropsError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("Got request error {0}!")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum SearchError {
#[error("header error ({0})")]
Props(#[from] PropsError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("Got request error {0}!")]
Request(#[from] GenericRequestError),
}
#[derive(Error, Debug)]
pub enum ReviewsError {
#[error("header error ({0})")]
Props(#[from] PropsError),
#[error("google returned an error ({0})")]
Google(#[from] GoogleError),
#[error("Got request error {0}!")]
Request(#[from] GenericRequestError),
}
pub trait IntoGoogleError<A> {
fn into_google_error(self, response: &crate::proto::ResponseWrapper) -> Result<A, GoogleError>;
fn into_google_error_map(self, function: impl FnOnce() -> String) -> Result<A, GoogleError>;
}
impl<A> IntoGoogleError<A> for Option<A> {
fn into_google_error(self, response: &crate::proto::ResponseWrapper) -> Result<A, GoogleError> {
self.map_or_else(
|| {
Err(GoogleError(response.commands.as_ref().map_or_else(
|| "Google returned... nothing?".to_string(),
|a| {
a.display_error_message
.clone()
.unwrap_or_else(|| "Google returned no error!".to_string())
},
)))
},
Ok,
)
}
fn into_google_error_map(self, function: impl FnOnce() -> String) -> Result<A, GoogleError> {
self.map_or_else(|| Err(GoogleError(function())), Ok)
}
}