leyline-http 0.1.1

HTTP client that mimics browsers on the wire
Documentation
use std::time::Duration;

use super::days_since_epoch;

#[derive(Default)]
pub(super) struct Date {
    day: u32,
    month: u32,
    year: u32,
    hour: u32,
    minute: u32,
    second: u32,
    time: bool,
}

pub(super) fn token(d: &mut Date, tok: &str) {
    if !d.time && tok.contains(':') {
        let parts: Vec<&str> = tok.split(':').collect();
        if parts.len() >= 2 {
            d.hour = parts[0].parse().unwrap_or(0);
            d.minute = parts[1].parse().unwrap_or(0);
            d.second = parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
            d.time = true;
        }
        return;
    }

    if let Ok(n) = tok.parse::<u32>() {
        if n > 99 {
            d.year = n;
        } else if d.day == 0 {
            d.day = n;
        } else if d.year == 0 {
            d.year = if n > 68 { 1900 + n } else { 2000 + n };
        }
        return;
    }

    let m = month(tok);
    if m > 0 {
        d.month = m;
    }
}

fn month(tok: &str) -> u32 {
    match tok.get(..3).map(|s| s.to_lowercase()).as_deref() {
        Some("jan") => 1,
        Some("feb") => 2,
        Some("mar") => 3,
        Some("apr") => 4,
        Some("may") => 5,
        Some("jun") => 6,
        Some("jul") => 7,
        Some("aug") => 8,
        Some("sep") => 9,
        Some("oct") => 10,
        Some("nov") => 11,
        Some("dec") => 12,
        _ => 0,
    }
}

pub(super) fn stamp(d: &Date) -> Option<Duration> {
    if d.day == 0 || d.month == 0 || d.year == 0 {
        return None;
    }

    let days = days_since_epoch(d.year, d.month, d.day)?;
    if days < 0 {
        return Some(Duration::ZERO);
    }
    let secs = (days as u64)
        .checked_mul(86400)?
        .checked_add(d.hour as u64 * 3600)?
        .checked_add(d.minute as u64 * 60)?
        .checked_add(d.second as u64)?;
    Some(Duration::from_secs(secs))
}