tudor-sql 0.2.0

Does sql stuff to todo.txt files
Documentation
use pest_consume::Parser;

use crate::sql::expression::parser::{ExpressionParser, Result, Rule};
use crate::sql::expression::value::*;
use crate::todo::Todo;

#[derive(Eq, PartialEq, Hash, Debug)]
pub enum TodoField {
    FullText,
    IsCompleted,
    Id,
    IsBlockingFor,
    IsBlocked,
    BlockedBy,
    CreationDate,
    CompletionDate,
    Priority,
    CanonicalContext,
    Contexts,
    CanonicalProject,
    Projects,
    DueDate,
    ThresholdDate,
    IsHidden,
}

impl TodoField {
    fn map_or_null<T, F: FnOnce(T) -> Value>(o: Option<T>, f: F) -> Value {
        match o {
            Some(t) => f(t),
            None => Value::Null,
        }
    }

    pub fn get_value(&self, t: &Todo) -> Value {
        let val = match self {
            TodoField::FullText => Value::Text(format!("{}", t)),
            TodoField::IsCompleted => Value::Boolean(t.is_completed),
            TodoField::Id => unimplemented!(),
            TodoField::IsBlockingFor => unimplemented!(),
            TodoField::IsBlocked => unimplemented!(),
            TodoField::BlockedBy => unimplemented!(),
            TodoField::CreationDate => TodoField::map_or_null(t.creation_date, Value::Date),
            TodoField::CompletionDate => TodoField::map_or_null(t.completion_date, Value::Date),
            TodoField::Priority => {
                TodoField::map_or_null(t.priority, |pri| Value::Text(pri.to_string()))
            }
            TodoField::CanonicalContext => {
                TodoField::map_or_null(t.canonical_context(), Value::Text)
            }
            TodoField::CanonicalProject => {
                TodoField::map_or_null(t.canonical_project(), Value::Text)
            }
            TodoField::Contexts => Value::Set(t.contexts.iter().map(|s| s.to_string()).collect()),
            TodoField::Projects => Value::Set(t.projects.iter().map(|s| s.to_string()).collect()),
            TodoField::DueDate => TodoField::map_or_null(t.due_date, Value::Date),
            TodoField::ThresholdDate => TodoField::map_or_null(t.threshold_date, Value::Date),
            TodoField::IsHidden => Value::Boolean(t.is_hidden),
        };
        val
    }

    pub fn parse(input: &str) -> Result<TodoField> {
        let nodes = ExpressionParser::parse(Rule::todo_field, input)?;
        let node = nodes.single()?;
        let v = ExpressionParser::todo_field(node)?;
        Ok(v)
    }
}