Add module src/free_api_v25/query/queryparams.rs

This commit is contained in:
Candifloss 2025-10-10 01:42:02 +05:30
parent 0c7839b92b
commit 96bd494161
2 changed files with 131 additions and 0 deletions

View File

@ -18,5 +18,10 @@
//! assert!(url.contains("q=London")); //! assert!(url.contains("q=London"));
//! ``` //! ```
pub mod queryparams;
pub mod units; pub mod units;
pub mod urls; pub mod urls;
pub use queryparams::*;
pub use units::*;
pub use urls::*;

View File

@ -0,0 +1,126 @@
use super::{
Units,
urls::{FORECAST_URL, WEATHER_URL},
};
/// Query parameters for `OpenWeatherMap` API.
///
/// **Note:** One of `city_id`, `city_name`, `(lat, lon)` pair, or `zip` **must** be provided,
/// otherwise URL building will fail.
#[derive(Debug, Clone)]
pub struct QueryParams {
/// Your `OpenWeatherMap` API key
pub api_key: String,
/// City ID (optional)
///
/// You can make an API call by city ID to get an unambiguous result for your city.
/// The list of city IDs (`city.list.json.gz`) can be downloaded [here](http://bulk.openweathermap.org/sample/).
pub city_id: Option<String>,
/// City name (optional)
///
/// You can call by city name, or city name + state code + country code.
/// Searching by state is only available for locations in the USA.
/// See: <https://openweathermap.org/current#name>
pub city_name: Option<String>,
/// Latitude (optional, must be used with `lon`)
pub lat: Option<f32>,
/// Longitude (optional, must be used with `lat`)
pub lon: Option<f32>,
/// Zip code (optional)
///
/// Format: `"94040,us"`. If the country code is not specified, it defaults to USA.
pub zip: Option<String>,
/// Units for temperature and wind (default `"Standard"`)
pub units: Units,
/// Language code for descriptions (default `"en"`)
pub lang: String,
}
impl QueryParams {
/// Build query URL for the `/weather` endpoint.
///
/// # Errors
///
/// Returns an `Err` if no valid location is specified
/// (`city_id`, `city_name`, `lat`/`lon`, or `zip` are all None).
///
/// # Example
///
/// ```
/// use owm_api25::query::{QueryParams, Units, WEATHER_URL};
///
/// let query = QueryParams {
/// api_key: "MY_API_KEY".to_string(),
/// city_name: Some("London".to_string()),
/// ..Default::default()
/// };
///
/// let url = query.weather_url().unwrap();
/// assert!(url.contains("q=London"));
/// assert!(url.contains("appid=MY_API_KEY"));
/// ```
pub fn weather_url(&self) -> Result<String, String> {
self.build_url(WEATHER_URL)
}
/// Build query URL for the `/forecast` endpoint.
///
/// # Errors
///
/// Returns an `Err` if no valid location is specified.
/// See `weather_url`.
pub fn forecast_url(&self) -> Result<String, String> {
self.build_url(FORECAST_URL)
}
/// Internal helper to build query URL.
///
/// # Errors
///
/// Returns an `Err` if no valid location is specified (`city_id`, `city_name`, `lat`/`lon`, or `zip`).
fn build_url(&self, base: &str) -> Result<String, String> {
let mut params = vec![
format!("appid={}", self.api_key),
format!("units={}", self.units),
format!("lang={}", self.lang),
"mode=json".to_string(),
];
if let Some(ref id) = self.city_id {
params.push(format!("id={id}"));
} else if let Some(ref name) = self.city_name {
params.push(format!("q={name}"));
} else if let (Some(lat), Some(lon)) = (self.lat, self.lon) {
params.push(format!("lat={lat}&lon={lon}"));
} else if let Some(ref zip) = self.zip {
params.push(format!("zip={zip}"));
} else {
return Err("No valid location field found".into());
}
Ok(format!("{base}?{}", params.join("&")))
}
}
/// Default values for query parameters
impl Default for QueryParams {
fn default() -> Self {
Self {
api_key: String::new(),
city_id: None,
city_name: None,
lat: None,
lon: None,
zip: None,
units: Units::Standard,
lang: "en".to_string(),
}
}
}