use regex::Regex;
pub fn add(left: u64, right: u64) -> u64 {
left + right
}
pub struct LatestIphone {
pub model: String,
pub price_usd: Option<u32>,
pub release_date: Option<String>, }
pub fn latest() -> LatestIphone {
LatestIphone {
model: "iPhone 17".to_string(),
price_usd: Some(799),
release_date: Some("2025-09-09".to_string()),
}
}
pub fn fetch_latest() -> Result<LatestIphone, String> {
let client = reqwest::blocking::Client::builder()
.user_agent("Mozilla/5.0 (compatible; iphone-crate/0.1; +https://gitee.com/luzhihaoTestingLab/useful-cargo-packages)")
.timeout(std::time::Duration::from_secs(10))
.build()
.map_err(|e| format!("client build error: {}", e))?;
let mut model: Option<String> = None;
let mut price: Option<u32> = None;
let mut release: Option<String> = None;
if let Ok(resp) = client.get("https://www.apple.com/iphone/").send() {
if resp.status().is_success() {
if let Ok(text) = resp.text() {
let re_model = Regex::new(r"iPhone\s+(\d{2})").unwrap();
let mut max_num: i32 = 0;
for cap in re_model.captures_iter(&text) {
let n: i32 = cap[1].parse().unwrap_or(0);
if n > max_num { max_num = n; }
}
if max_num > 0 { model = Some(format!("iPhone {}", max_num)); }
let re_price = Regex::new(r"From\s*\$([0-9]{3,4})").unwrap();
if let Some(cap) = re_price.captures(&text) {
price = cap[1].parse().ok();
}
}
}
}
if model.is_some() {
if let Ok(resp) = client.get("https://www.apple.com/newsroom/").send() {
if resp.status().is_success() {
if let Ok(text) = resp.text() {
let re_date = Regex::new(r#"datetime=\"(\d{4}-\d{2}-\d{2})\""#).unwrap();
if let Some(m) = &model {
if let Some(idx) = text.find(m) {
let start = idx.saturating_sub(600);
let end = std::cmp::min(text.len(), idx + 600);
let slice = &text[start..end];
if let Some(cap) = re_date.captures(slice) {
release = Some(cap[1].to_string());
}
}
}
if release.is_none() {
if let Some(cap) = re_date.captures(&text) {
release = Some(cap[1].to_string());
}
}
}
}
}
}
if let Some(m) = model {
Ok(LatestIphone { model: m, price_usd: price, release_date: release })
} else {
Ok(latest())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn latest_static_values() {
let li = latest();
assert_eq!(li.model, "iPhone 17");
assert_eq!(li.price_usd, Some(799));
assert_eq!(li.release_date.as_deref(), Some("2025-09-09"));
}
}