ofdb_entities/
event.rs

1use std::str::FromStr;
2
3use crate::{contact::*, email::*, id::*, location::*, time::*, url::*};
4
5#[derive(Debug, Copy, Clone, Eq, PartialEq)]
6pub enum RegistrationType {
7    Email,
8    Phone,
9    Homepage,
10}
11
12#[derive(Debug)]
13pub struct RegistrationTypeParseError;
14
15impl FromStr for RegistrationType {
16    type Err = RegistrationTypeParseError;
17    fn from_str(s: &str) -> Result<RegistrationType, Self::Err> {
18        match &*s.to_lowercase() {
19            "email" => Ok(RegistrationType::Email),
20            "telephone" => Ok(RegistrationType::Phone),
21            "homepage" => Ok(RegistrationType::Homepage),
22            _ => Err(RegistrationTypeParseError),
23        }
24    }
25}
26
27#[rustfmt::skip]
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct Event {
30    pub id           : Id,
31    pub title        : String,
32    pub description  : Option<String>,
33    // Both start/end time stamps are stored with second precision!
34    // TODO: use something like
35    // <https://docs.rs/icalendar/latest/icalendar/enum.DatePerhapsTime.html>
36    pub start        : Timestamp,
37    pub end          : Option<Timestamp>,
38    pub location     : Option<Location>,
39    pub contact      : Option<Contact>,
40    pub tags         : Vec<String>,
41    pub homepage     : Option<Url>,
42    pub created_by   : Option<EmailAddress>,
43    pub registration : Option<RegistrationType>,
44    // TODO: Switch archived time stamp to millisecond precision?
45    pub archived     : Option<Timestamp>,
46    pub image_url     : Option<Url>,
47    pub image_link_url: Option<Url>,
48}
49
50impl Event {
51    /// Deprecated: Only for backward compatibility!
52    pub fn organizer(&self) -> Option<&String> {
53        self.contact.as_ref().and_then(|c| c.name.as_ref())
54    }
55}
56
57impl Event {
58    pub fn strip_activity_details(self) -> Self {
59        Self {
60            created_by: None,
61            ..self
62        }
63    }
64
65    pub fn strip_contact_details(self) -> Self {
66        Self {
67            contact: None,
68            ..self
69        }
70    }
71
72    pub fn is_owned<'a>(&self, moderated_tags: impl IntoIterator<Item = &'a str>) -> bool {
73        // Exclusive ownership of events is determined by the associated tags
74        moderated_tags
75            .into_iter()
76            .any(|moderated_tag| self.tags.iter().any(|tag| tag == moderated_tag))
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    #[test]
84    fn registration_type_from_str() {
85        assert_eq!(
86            RegistrationType::from_str("email").unwrap(),
87            RegistrationType::Email
88        );
89        assert_eq!(
90            RegistrationType::from_str("eMail").unwrap(),
91            RegistrationType::Email
92        );
93        assert_eq!(
94            RegistrationType::from_str("telephone").unwrap(),
95            RegistrationType::Phone
96        );
97        assert_eq!(
98            RegistrationType::from_str("Telephone").unwrap(),
99            RegistrationType::Phone
100        );
101        assert_eq!(
102            RegistrationType::from_str("homepage").unwrap(),
103            RegistrationType::Homepage
104        );
105        assert_eq!(
106            RegistrationType::from_str("Homepage").unwrap(),
107            RegistrationType::Homepage
108        );
109        assert!(RegistrationType::from_str("foo").is_err());
110        assert!(RegistrationType::from_str("").is_err());
111    }
112}