calcard 0.3.3

iCalendar/JSCalendar and vCard/JSContact parsing, building and conversion library for Rust
Documentation
/*
 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
 *
 * SPDX-License-Identifier: Apache-2.0 OR MIT
 */

use super::{
    ArchivedICalendar, ArchivedICalendarComponent, ArchivedICalendarComponentType,
    ArchivedICalendarEntry, ArchivedICalendarProperty, ArchivedICalendarValue,
};
use crate::{common::timezone::Tz, icalendar::ICalendarParameterName};
use std::str::FromStr;

impl ArchivedICalendar {
    pub fn timezones(&self) -> impl Iterator<Item = &ArchivedICalendarComponent> {
        self.components.iter().filter(|comp| {
            matches!(
                comp.component_type,
                ArchivedICalendarComponentType::VTimezone
            )
        })
    }

    pub fn is_timezone(&self) -> bool {
        self.timezones().count() == 1
    }
}

impl ArchivedICalendarComponent {
    pub fn timezone(&self) -> Option<(&str, Tz)> {
        let mut tz_name = None;
        let mut tz_id = None;
        let mut tz_lic = None;
        let mut tz_cdo_id = None;

        for entry in self.entries.iter() {
            match (&entry.name, entry.values.first()) {
                (ArchivedICalendarProperty::Tzid, Some(ArchivedICalendarValue::Text(id))) => {
                    tz_id = Tz::from_str(id.as_str()).ok();
                    tz_name = Some(id.as_str());
                }
                (
                    ArchivedICalendarProperty::Other(value),
                    Some(ArchivedICalendarValue::Text(id)),
                ) => {
                    hashify::fnc_map!(value.as_bytes(),
                        "X-LIC-LOCATION" => {
                            tz_lic = Tz::from_str(id.strip_prefix("SystemV/").unwrap_or(id.as_str())).ok();
                        },
                        "X-MICROSOFT-CDO-TZID" => {
                            tz_cdo_id = Tz::from_ms_cdo_zone_id(id);
                        },
                        _ => {}
                    );
                }
                _ => (),
            }
        }

        tz_name.and_then(|name| tz_id.or(tz_lic).or(tz_cdo_id).map(|tz| (name, tz)))
    }
}

impl ArchivedICalendarEntry {
    pub fn tz_id(&self) -> Option<&str> {
        self.parameters(&ICalendarParameterName::Tzid)
            .find_map(|param| param.as_text())
    }
}