aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/remind/database.rs
blob: c0c127ef68ee6d476570b56e434086d68b7b6f02 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#[cfg(feature = "mysql")]
extern crate dotenv;

use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::fmt;

use chrono::NaiveDateTime;

use super::error::*;

#[derive(Clone, Debug)]
pub struct Event {
    pub id: i64,
    pub receiver: String,
    pub content: String,
    pub author: String,
    pub time: NaiveDateTime,
    pub repeat: Option<u64>,
}

impl fmt::Display for Event {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}: {} reminds {} to \"{}\" at {}",
            self.id, self.author, self.receiver, self.content, self.time
        )
    }
}

#[derive(Debug)]
pub struct NewEvent<'a> {
    pub receiver: &'a str,
    pub content: &'a str,
    pub author: &'a str,
    pub time: &'a NaiveDateTime,
    pub repeat: Option<u64>,
}

pub trait Database: Send + Sync {
    fn insert_event(&mut self, event: &NewEvent) -> Result<(), RemindError>;
    fn update_event_time(&mut self, id: i64, &NaiveDateTime) -> Result<(), RemindError>;
    fn get_events_before(&self, time: &NaiveDateTime) -> Result<Vec<Event>, RemindError>;
    fn get_user_events(&self, user: &str) -> Result<Vec<Event>, RemindError>;
    fn get_event(&self, id: i64) -> Result<Event, RemindError>;
    fn delete_event(&mut self, id: i64) -> Result<(), RemindError>;
}

// HashMap
impl Database for HashMap<i64, Event> {
    fn insert_event(&mut self, event: &NewEvent) -> Result<(), RemindError> {
        let mut id = 0;
        while self.contains_key(&id) {
            id += 1;
        }

        let event = Event {
            id: id,
            receiver: event.receiver.to_owned(),
            content: event.content.to_owned(),
            author: event.author.to_owned(),
            time: event.time.clone(),
            repeat: event.repeat,
        };

        match self.insert(id, event) {
            None => Ok(()),
            Some(_) => Err(ErrorKind::Duplicate)?,
        }
    }

    fn update_event_time(&mut self, id: i64, time: &NaiveDateTime) -> Result<(), RemindError> {
        let entry = self.entry(id);

        match entry {
            Entry::Occupied(mut v) => v.get_mut().time = *time,
            Entry::Vacant(_) => return Err(ErrorKind::NotFound.into()),
        }

        Ok(())
    }

    fn get_events_before(&self, time: &NaiveDateTime) -> Result<Vec<Event>, RemindError> {
        let mut events = Vec::new();

        for (_, event) in self.iter() {
            if &event.time < time {
                events.push(event.clone())
            }
        }

        if events.is_empty() {
            Err(ErrorKind::NotFound.into())
        } else {
            Ok(events)
        }
    }

    fn get_user_events(&self, user: &str) -> Result<Vec<Event>, RemindError> {
        let mut events = Vec::new();

        for (_, event) in self.iter() {
            if event.receiver.eq_ignore_ascii_case(user) {
                events.push(event.clone())
            }
        }

        if events.is_empty() {
            Err(ErrorKind::NotFound.into())
        } else {
            Ok(events)
        }
    }

    fn get_event(&self, id: i64) -> Result<Event, RemindError> {
        Ok(self.get(&id)
            .map(|ev| ev.clone())
            .ok_or(ErrorKind::NotFound)?)
    }

    fn delete_event(&mut self, id: i64) -> Result<(), RemindError> {
        match self.remove(&id) {
            Some(_) => Ok(()),
            None => Err(ErrorKind::NotFound)?,
        }
    }
}