drive-v3 0.6.0

A library for interacting the Google Drive API
Documentation
use std::{fmt, io};
use serde::Deserialize;

/// Types of errors that can happen during usage.
#[derive(Debug, PartialEq, Eq)]
pub enum ErrorKind {
    /// Errors related to IO operations like reading or writing to files.
    IO,

    /// Errors related to serializing or deserializing structs to and from JSON.
    Json,

    /// Errors related to the construction of an URL.
    UrlParsing,

    /// Errors related to request operations like sending GET or POST requests or getting the body of a response.
    Request,

    /// A request to the Google Drive API returned an error response.
    Response,

    /// Error during the decoding of the SHA-256 hash required for the creation of a
    /// [`code verifier`](https://developers.google.com/identity/protocols/oauth2/native-app#step1-code-verifier).
    HexDecoding,

    /// The `scopes` in an [`AccessToken`](crate::AccessToken) do not match those required for an operation.
    MismatchedScopes,

    /// An `authorization request` sent to the Google Drive API returned different `state` to the one originally sent.
    MismatchedState,

    /// A created [`LocalServer`](crate::LocalServer) was unable to listen for requests.
    LocalServer,

    /// An authorization request did not include the `code` query element required for authentication.
    NoAuthorizationCode,
}

/// Errors that can arise during usage.
#[derive(Debug, PartialEq, Eq)]
pub struct Error {
    /// Type of the error.
    pub kind: ErrorKind,

    /// Message associated with the error.
    pub message: String,
}

impl fmt::Display for Error {
    fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl Error {
    /// creates a new [`Error`] with the given kind and message.
    pub fn new<T: AsRef<str>> ( kind: ErrorKind, message: T ) -> Self {
        Self { kind, message: message.as_ref().to_string() }
    }
}

#[derive(Deserialize)]
struct GoogleDriveAPIError {
    code: usize,
    message: String,
}

#[derive(Deserialize)]
struct GoogleDriveAPIResponse {
    error: GoogleDriveAPIError,
}

#[doc(hidden)]
impl From<reqwest::blocking::Response> for Error {
    fn from( response: reqwest::blocking::Response ) -> Self {
        let response_code = format!("{}", response.status());

        let body = match response.text() {
            Ok(body) => body,
            Err(error) => return Self {
                kind: ErrorKind::Response,
                message: format!("{}, (unable to get the body of this error response)", error),
            },
        };

        match serde_json::from_str::<GoogleDriveAPIResponse>(&body) {
            Ok(response) => {
                Self {
                    kind: ErrorKind::Response,
                    message: format!("({}) {}", response.error.code, response.error.message),
                }
            },
            Err(_) => {
                Self {
                    kind: ErrorKind::Response,
                    message: format!("({}) {}", response_code, body),
                }
            }
        }
    }
}

#[doc(hidden)]
impl From<io::Error> for Error {
    fn from( error: io::Error ) -> Self {
        Self {
            kind: ErrorKind::IO,
            message: error.to_string(),
        }
    }
}

#[doc(hidden)]
impl From<serde_json::Error> for Error {
    fn from( error: serde_json::Error ) -> Self {
        Self {
            kind: ErrorKind::Json,
            message: error.to_string(),
        }
    }
}

#[doc(hidden)]
impl From<hex::FromHexError> for Error {
    fn from( error: hex::FromHexError ) -> Self {
        Self {
            kind: ErrorKind::HexDecoding,
            message: error.to_string(),
        }
    }
}

#[doc(hidden)]
impl From<url::ParseError> for Error {
    fn from( error: url::ParseError ) -> Self {
        Self {
            kind: ErrorKind::UrlParsing,
            message: error.to_string(),
        }
    }
}

#[doc(hidden)]
impl From<reqwest::Error> for Error {
    fn from( error: reqwest::Error ) -> Self {
        Self {
            kind: ErrorKind::Request,
            message: error.to_string(),
        }
    }
}

#[doc(hidden)]
impl From<reqwest::header::InvalidHeaderValue> for Error {
    fn from( error: reqwest::header::InvalidHeaderValue ) -> Self {
        Self {
            kind: ErrorKind::Request,
            message: error.to_string(),
        }
    }
}

#[doc(hidden)]
impl From<reqwest::header::ToStrError> for Error {
    fn from( error: reqwest::header::ToStrError ) -> Self {
        Self {
            kind: ErrorKind::Request,
            message: error.to_string(),
        }
    }
}