Functional Weave
Code in Rust

todo.export-csv@1.0.0

impl/rust.rs

1,834 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::todo_item::{todos_from_value, Todo};  ← from todo.item ^1.0.0 · built alongside by fune

const HEADER: [&str; 13] = [
    "id", "title", "notes", "done", "priority", "due", "tags",
    "recurrenceFrequency", "recurrenceInterval", "recurrenceAnchor", "createdAt", "completedAt", "order",
];

/// Quote a field only when RFC 4180 needs it: a comma, a double quote, CR or LF.
fn field(text: &str) -> String {
    if !text.contains(|c: char| c == ',' || c == '"' || c == '\r' || c == '\n') {
        return text.to_string();
    }
    format!("\"{}\"", text.replace('"', "\"\""))
}

/// Todos as CSV under a fixed 13-column header, one CRLF-ended row each, in
/// the order given. Nothing is escaped for spreadsheets (see README).
pub fn export_csv(todos: &[Todo]) -> String {
    let mut out = HEADER.join(",");
    out.push_str("\r\n");
    for todo in todos {
        let rule = todo.recurrence.as_ref();
        let cells: [String; 13] = [
            todo.id.clone(),
            todo.title.clone(),
            todo.notes.clone().unwrap_or_default(),
            (if todo.done { "true" } else { "false" }).to_string(),
            todo.priority.clone(),
            todo.due.clone().unwrap_or_default(),
            todo.tags.join(" "),
            rule.map(|r| r.frequency.clone()).unwrap_or_default(),
            rule.map(|r| r.interval.to_string()).unwrap_or_default(),
            rule.map(|r| r.anchor.clone()).unwrap_or_default(),
            todo.created_at.clone(),
            todo.completed_at.clone().unwrap_or_default(),
            todo.order.to_string(),
        ];
        let row: Vec<String> = cells.iter().map(|c| field(c)).collect();
        out.push_str(&row.join(","));
        out.push_str("\r\n");
    }
    out
}

pub fn fune_vector(args: &[Value]) -> Value {
    Value::str(&export_csv(&todos_from_value(&args[0])))
}