tdo_core/
list.rs

1//! General implementation of todo lists.
2use todo::Todo;
3use error::*;
4
5/// Simple todo list structure.
6///
7/// Todos can be grouped together in so called todo lists (as in the real world).
8/// Therefore, the `TodoList` struct can be used. It's a simple data structure that holds a
9/// number of `Todo` items and offers all basic functions for managing them.
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct TodoList {
12    /// Name of the todo list.
13    pub name: String,
14    /// The actual vector of `Todo` items.
15    pub list: Vec<Todo>,
16}
17
18impl TodoList {
19    /// Create a new list with the given name.
20    ///
21    /// # Example
22    ///
23    /// ```
24    /// # use tdo_core::list::*;
25    /// let mut list = TodoList::new("important");
26    /// ```
27    pub fn new(name: &str) -> TodoList {
28        TodoList {
29            name: name.to_string(),
30            list: Vec::new(),
31        }
32    }
33
34    /// Add a new todo to the list.
35    ///
36    /// # Example
37    ///
38    /// ```
39    /// # use tdo_core::list::*;
40    /// # use tdo_core::todo::*;
41    /// # let mut list = TodoList::new("important");
42    /// list.add(Todo::new(0,"A first important todo", None));
43    /// ```
44    pub fn add(&mut self, new_todo: Todo) {
45        self.list.push(new_todo);
46    }
47
48    /// Check if the list contains a todo with the given ID.
49    ///
50    /// This function returns a `TdoResult`, wich will contion a `TodoError::NotInList`
51    /// if the list does not contain any todo with the given ID or the position in the list.
52    pub fn contains_id(&self, id: u32) -> TdoResult<usize> {
53        match self.list.iter().position(|x| x.id == id) {
54            Some(index) => Ok(index),
55            None => Err(ErrorKind::TodoError(todo_error::ErrorKind::NotInList).into()),
56        }
57    }
58    /// Mark a todo from the list with the given ID as done.
59    ///
60    /// This function returns a `TdoResult`, which will contain a `TodoError::NotInList`
61    /// if the list does not contain any todo with the given ID.
62    pub fn done_id(&mut self, id: u32) -> TdoResult<()> {
63        match self.contains_id(id) {
64            Ok(index) => Ok(self.list[index].set_done()),
65            _ => Err(ErrorKind::TodoError(todo_error::ErrorKind::NotInList).into()),
66        }
67    }
68
69    /// Remove a todo with the given ID from the list.
70    ///
71    /// This function returns a `TdoResult`, which will contain the removed Todo itself or a
72    /// `TodoError::NotInList` if the list does not contain any todo with the given id.
73    pub fn remove_id(&mut self, id: u32) -> TdoResult<Todo> {
74        match self.contains_id(id) {
75            Ok(index) => Ok(self.list.remove(index)),
76            _ => Err(ErrorKind::TodoError(todo_error::ErrorKind::NotInList).into()),
77        }
78    }
79
80    /// Search for all undone todos in the list.
81    ///
82    /// Returns a vector of all undone todos.
83    pub fn list_undone(&self) -> Vec<Todo> {
84        let mut undone: Vec<Todo> = vec![];
85        for entry in self.to_owned().list.into_iter() {
86            if !entry.done {
87                undone.push(entry);
88            }
89        }
90        undone
91    }
92
93    /// Remove all done todos from the list.
94    pub fn clean(&mut self) {
95        for entry in self.to_owned().list.into_iter() {
96            if entry.done {
97                let _ = self.remove_id(entry.id);
98            }
99        }
100    }
101
102    /// Remove a todo with a specific ID from the list.
103    pub fn pop_id(&mut self, todo_id: u32) -> TdoResult<Todo> {
104        let list_pos = self.contains_id(todo_id)?;
105
106        Ok(self.list.remove(list_pos))
107    }
108
109    /// Insert an existing todo into the list, preserving the ordering of the internal list.
110    pub fn insert_todo(&mut self, todo: Todo) {
111        let insert_id = self.list
112            .iter()
113            .fold(0, |acc, &ref x| if todo.id > x.id { acc + 1 } else { acc });
114
115        self.list.insert(insert_id, todo);
116    }
117}
118
119/// Instanciates a _default_ `TodoList`.
120/// This function is invoked when a `Tdo` container structure is instanciated.
121impl Default for TodoList {
122    fn default() -> TodoList {
123        TodoList {
124            name: "default".to_string(),
125            list: Vec::new(),
126        }
127    }
128}