Files
contextswitch/src/lib.rs

203 lines
5.3 KiB
Rust

use chrono::{DateTime, Utc};
use http::uri::Uri;
use serde::{Deserialize, Serialize};
use std::fmt;
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, Eq)]
#[serde(rename_all = "lowercase")]
pub enum Recurrence {
Daily,
Weekly,
Monthly,
Yearly,
}
impl fmt::Display for Recurrence {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", format!("{:?}", self).to_lowercase())
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, Eq)]
#[serde(rename_all = "lowercase")]
pub enum Status {
Pending,
Completed,
Recurring,
Deleted,
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", format!("{:?}", self).to_lowercase())
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, Eq)]
pub enum Priority {
H,
M,
L,
}
impl fmt::Display for Priority {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
pub struct Bookmark {
#[serde(with = "uri")]
pub uri: Uri,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<BookmarkContent>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
pub struct BookmarkContent {
pub title: String,
pub content_preview: Option<String>,
}
pub mod uri {
use http::uri::Uri;
use serde::{self, Deserialize, Deserializer, Serializer};
pub fn serialize<S>(uri: &Uri, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let uri_str = uri.to_string();
serializer.serialize_str(&uri_str)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Uri, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
s.parse::<Uri>().map_err(serde::de::Error::custom)
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
pub struct ContextswitchData {
pub bookmarks: Vec<Bookmark>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
pub struct TaskId(pub Uuid);
impl fmt::Display for TaskId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct Task {
pub id: TaskId,
#[serde(with = "tw_date_format")]
pub entry: DateTime<Utc>,
#[serde(with = "tw_date_format")]
pub modified: DateTime<Utc>,
pub status: Status,
pub description: String,
pub urgency: f64,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "opt_tw_date_format"
)]
pub due: Option<DateTime<Utc>>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "opt_tw_date_format"
)]
pub start: Option<DateTime<Utc>>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "opt_tw_date_format"
)]
pub end: Option<DateTime<Utc>>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "opt_tw_date_format"
)]
pub wait: Option<DateTime<Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<TaskId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub project: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub priority: Option<Priority>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub recur: Option<Recurrence>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contextswitch: Option<ContextswitchData>,
}
#[derive(Deserialize, Serialize)]
pub struct NewTask {
pub definition: String,
}
pub mod tw_date_format {
use chrono::{DateTime, TimeZone, Utc};
use serde::{self, Deserialize, Deserializer, Serializer};
const FORMAT: &str = "%Y%m%dT%H%M%SZ";
pub fn serialize<S>(date: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = format!("{}", date.format(FORMAT));
serializer.serialize_str(&s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Utc.datetime_from_str(&s, FORMAT)
.map_err(serde::de::Error::custom)
}
}
pub mod opt_tw_date_format {
use chrono::{DateTime, TimeZone, Utc};
use serde::{self, Deserialize, Deserializer, Serializer};
const FORMAT: &str = "%Y%m%dT%H%M%SZ";
pub fn serialize<S>(date: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(ref d) = *date {
return serializer.serialize_str(&d.format(FORMAT).to_string());
}
serializer.serialize_none()
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Utc.datetime_from_str(&s, FORMAT)
.map(Some)
.map_err(serde::de::Error::custom)
}
}