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
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::fmt;

use serde::{Deserialize, Serialize};

use crate::Error;

#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ApiResponse<T> {
    Error { error: ErrorResponse },
    Ok(T),
}

impl<T> Into<Result<T, Error>> for ApiResponse<T> {
    fn into(self) -> Result<T, Error> {
        match self {
            ApiResponse::Error { error } => Err(Error::Api(error)),
            ApiResponse::Ok(inner) => Ok(inner),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorResponse {
    pub code: ErrorCode,
    pub message: String,
}

#[derive(Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub enum ErrorCode {
    // 400 Bad Request
    BadWords,
    BadCoordinates,
    BadLanguage,
    BadFormat,
    BadClipToPolygon,
    MissingWords,
    MissingInput,
    MissingBoundingBox,
    DuplicateParameter,

    // 401 Unauthorized
    MissingKey,
    InvalidKey,

    // 404 Not Found
    NotFound,

    // 405 Method Not Allowed
    MethodNotAllowed,

    // 500 Internal Server Error
    InternalServerError,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Coords {
    pub country: String,
    pub square: Square,
    pub nearest_place: Option<String>,
    pub coordinates: GeoCoords,
    pub words: String,
    pub language: String,
    pub map: url::Url,
}

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

#[derive(Debug, Deserialize, Serialize)]
pub struct Square {
    pub southwest: GeoCoords,
    pub northeast: GeoCoords,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GeoCoords {
    pub lat: f64,
    pub lng: f64,
}

impl Into<geo_types::Point<f64>> for GeoCoords {
    fn into(self) -> geo_types::Point<f64> {
        geo_types::Point::new(self.lng, self.lat)
    }
}

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

#[derive(Debug, Deserialize, Serialize)]
pub struct AvailableLanguages {
    pub languages: Vec<Language>,
}

impl fmt::Display for AvailableLanguages {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            self.languages
                .iter()
                .map(|lang| lang.to_string())
                .collect::<Vec<_>>()
                .join(",")
        )
    }
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Language {
    code: String,
    name: String,
    native_name: String,
}

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