IslandPenguin

task.rs

Mar 25th, 2021 (edited)
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 2.95 KB | None | 0 0
  1. use chrono::{serde::ts_seconds, DateTime, Local, Utc};
  2. use std::fmt;
  3. use serde::{Deserialize,Serialize};
  4. use std::{fs::OpenOptions, io::ErrorKind, path::PathBuf};
  5. use std::io::{Error,Result,Seek,SeekFrom,};  // Include the error type
  6. use std::fs::File;
  7.  
  8.  
  9. #[derive(Debug, Deserialize, Serialize)]
  10. pub struct Tasks {
  11.     pub tasklist: Vec<Task>,
  12. }
  13.  
  14. impl Tasks {
  15.     pub fn new(tasks:Vec<Task>) -> Tasks {
  16.         Tasks {
  17.             tasklist: tasks
  18.         }
  19.     }
  20. }
  21.  
  22. #[derive(Debug, Deserialize, Serialize)]
  23. pub struct Task {
  24.     pub text: String,
  25.  
  26.     #[serde(with = "ts_seconds")]
  27.     pub created_at: DateTime<Utc>,
  28. }
  29.  
  30. impl Task {
  31.     pub fn new(text: String) -> Task {
  32.         let created_at: DateTime<Utc> = Utc::now();
  33.         Task { text, created_at }
  34.     }
  35. }
  36. pub fn add_task(todo_path: PathBuf, task: Task) -> Result<()> {
  37.     let file = OpenOptions::new()
  38.         .read(true)
  39.         .write(true)
  40.         .create(true)
  41.         .open(todo_path)?;
  42.     let mut tasks = collect_tasks(&file)?.tasklist;
  43.     tasks.push(task);
  44.     serde_json::to_writer(file, &Tasks::new(tasks))?;
  45.     Ok(())
  46. }
  47. pub fn complete_task(todo_path: PathBuf, task_position: usize) -> Result<()> {
  48.     // Open the file.
  49.     let file = OpenOptions::new()
  50.         .read(true)
  51.         .write(true)
  52.         .open(todo_path)?;
  53.  
  54.     // Consume file's contents as a vector of tasks.
  55.     let mut tasks = collect_tasks(&file)?.tasklist;
  56.  
  57.     // Try to remove the task.
  58.     if task_position == 0 || task_position > tasks.len() {
  59.         return Err(Error::new(ErrorKind::InvalidInput, "Invalid Task ID"));
  60.     }
  61.     tasks.remove(task_position - 1);
  62.  
  63.     // Write the modified task list back into the file.
  64.     file.set_len(0)?;
  65.     serde_json::to_writer(file, &Tasks::new(tasks))?;
  66.     Ok(())
  67. }
  68.  
  69. fn collect_tasks(mut file: &File) -> Result<Tasks> {
  70.     file.seek(SeekFrom::Start(0))?; // Rewind the file before.
  71.     let tasks = match serde_json::from_reader(file) {
  72.         Ok(tasks) => tasks,
  73.         Err(e) if e.is_eof() => Tasks::new(Vec::new()),
  74.         Err(e) => Err(e)?,
  75.     };
  76.     file.seek(SeekFrom::Start(0))?; // Rewind the file after.
  77.     Ok(tasks)
  78. }
  79. pub fn list_tasks(todo_path: PathBuf) -> Result<()> {
  80.     // Open the file.
  81.     let file = OpenOptions::new().read(true).open(todo_path)?;
  82.     // Parse the file and collect the tasks.
  83.     let tasks = collect_tasks(&file)?.tasklist;
  84.  
  85.     // Enumerate and display tasks, if any.
  86.     if tasks.is_empty() {
  87.         println!("Task list is empty!");
  88.     } else {
  89.         let mut order: u32 = 1;
  90.         for task in tasks {
  91.             println!("{}: {}", order, task);
  92.             order += 1;
  93.         }
  94.     }
  95.  
  96.     impl fmt::Display for Task {
  97.         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  98.            let created_at = self.created_at.with_timezone(&Local).format("%F %H:%M");
  99.            write!(f, "{:<50} [{}]", self.text, created_at)
  100.        }
  101.    }
  102.    
  103.    Ok(())
  104. }
  105.  
Add Comment
Please, Sign In to add comment