Functional Weave
Code in TypeScript

todo.tag-counts@1.0.0

impl/rust.rs

1,632 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::collections_sort_by::sort_by;  ← from collections.sort-by ^1.0.0 · built alongside by fune
use super::todo_item::{todo_from_value, Todo};  ← from todo.item ^1.0.0 · built alongside by fune

/// How many todos carry each tag, for a tag sidebar: a todo counts once per
/// tag, done todos only when `include_done`, most used first, then tag in
/// code-point order.
pub fn tag_counts(todos: &[Todo], include_done: bool) -> Vec<TagCount> {
    let mut counts: Vec<(String, i64)> = Vec::new();
    for todo in todos {
        if todo.done && !include_done {
            continue;
        }
        let mut seen: Vec<&String> = Vec::new();
        for tag in &todo.tags {
            if seen.contains(&tag) {
                continue;
            }
            seen.push(tag);
            match counts.iter_mut().find(|(t, _)| t == tag) {
                Some(entry) => entry.1 += 1,
                None => counts.push((tag.clone(), 1)),
            }
        }
    }
    let rows: Vec<Value> = counts
        .iter()
        .map(|(tag, count)| Value::obj(vec![("tag", Value::str(tag)), ("count", Value::Int(*count))]))
        .collect();
    sort_by(&sort_by(&rows, "tag", "asc"), "count", "desc")
        .iter()
        .map(|r| TagCount { tag: r.get("tag").as_str().to_string(), count: r.get("count").as_i64() })
        .collect()
}

pub fn tag_count_to_value(row: &TagCount) -> Value {
    Value::obj(vec![("tag", Value::str(&row.tag)), ("count", Value::Int(row.count))])
}

pub fn fune_vector(args: &[Value]) -> Value {
    let todos: Vec<Todo> = args[0].as_arr().iter().map(todo_from_value).collect();
    Value::Arr(tag_counts(&todos, args[1].as_bool()).iter().map(tag_count_to_value).collect())
}