Skip to main content

macroonz_compiler/token/generation/
project.rs

1//! Conventional Rust projections over informed bounded values.
2//!
3//! The informed values own membership and order, while the caller owns every token written for one row and every item surrounding the returned expression.
4
5use super::compose::{comma_many, group};
6use super::{GENERATED_TOKEN_LIMIT, GeneratedDelimiter, GeneratedRowRefusal, GeneratedToken};
7use crate::bounded::{KeyedRoster, KeyedRosterAssignment, NonEmpty, NonEmptyError, Overflow};
8
9/// Projects one keyed roster into a borrowed Rust slice expression in retained order.
10///
11/// The caller supplies every row's tokens and remains responsible for any item name, visibility, element type, and semantic body surrounding the expression.
12///
13/// # Errors
14///
15/// Returns the first [`Overflow`] produced by the row projection or by the completed bracket group.
16pub fn keyed_roster_slice<T, K, const N: usize>(
17    roster: &KeyedRoster<T, K, N>,
18    mut row: impl FnMut(usize, &K, &T) -> Result<Vec<GeneratedToken>, Overflow>,
19) -> Result<Vec<GeneratedToken>, Overflow> {
20    let rows = roster
21        .indexed()
22        .map(|(index, key, member)| row(index, key, member))
23        .collect::<Result<Vec<_>, _>>()?;
24    borrowed_slice(rows)
25}
26
27/// Projects one keyed roster into a flat item run in retained order.
28///
29/// The caller supplies every row's complete tokens and remains responsible for the meaning of each item.
30///
31/// # Errors
32///
33/// Returns the first [`GeneratedRowRefusal`] where a callback refuses, emits no token, or emits more than the generated-token magnitude.
34pub fn keyed_roster_items<T, K, const N: usize>(
35    roster: &KeyedRoster<T, K, N>,
36    mut row: impl FnMut(usize, &K, &T) -> Result<Vec<GeneratedToken>, Overflow>,
37) -> Result<Vec<GeneratedToken>, GeneratedRowRefusal> {
38    let mut items = Vec::new();
39    for (index, key, member) in roster.indexed() {
40        let row = row(index, key, member)
41            .map_err(|cause| GeneratedRowRefusal::at(index, NonEmptyError::Overflow(cause)))?;
42        let row = NonEmpty::<GeneratedToken, GENERATED_TOKEN_LIMIT>::new(row)
43            .map_err(|cause| GeneratedRowRefusal::at(index, cause))?;
44        items.extend(row.iter().cloned());
45    }
46    Ok(items)
47}
48
49/// Projects one exact keyed assignment into a borrowed Rust slice expression in denominator order.
50///
51/// The caller supplies every row's tokens and remains responsible for any item name, visibility, element type, payload meaning, and semantic body surrounding the expression.
52///
53/// # Errors
54///
55/// Returns the first [`Overflow`] produced by the row projection or by the completed bracket group.
56pub fn keyed_assignment_slice<D, K, P, S, const N: usize>(
57    assignment: &KeyedRosterAssignment<D, K, P, S, N>,
58    mut row: impl FnMut(usize, &K, &D, &S, &P) -> Result<Vec<GeneratedToken>, Overflow>,
59) -> Result<Vec<GeneratedToken>, Overflow> {
60    let rows = assignment
61        .indexed()
62        .map(|(index, key, member, seat, payload)| row(index, key, member, seat, payload))
63        .collect::<Result<Vec<_>, _>>()?;
64    borrowed_slice(rows)
65}
66
67/// Projects one exact keyed assignment into a flat item run in denominator order.
68///
69/// The caller supplies every row's complete tokens and remains responsible for the meaning of each item.
70///
71/// # Errors
72///
73/// Returns the first [`GeneratedRowRefusal`] where a callback refuses, emits no token, or emits more than the generated-token magnitude.
74pub fn keyed_assignment_items<D, K, P, S, const N: usize>(
75    assignment: &KeyedRosterAssignment<D, K, P, S, N>,
76    mut row: impl FnMut(usize, &K, &D, &S, &P) -> Result<Vec<GeneratedToken>, Overflow>,
77) -> Result<Vec<GeneratedToken>, GeneratedRowRefusal> {
78    let mut items = Vec::new();
79    for (index, key, member, seat, payload) in assignment.indexed() {
80        let row = row(index, key, member, seat, payload)
81            .map_err(|cause| GeneratedRowRefusal::at(index, NonEmptyError::Overflow(cause)))?;
82        let row = NonEmpty::<GeneratedToken, GENERATED_TOKEN_LIMIT>::new(row)
83            .map_err(|cause| GeneratedRowRefusal::at(index, cause))?;
84        items.extend(row.iter().cloned());
85    }
86    Ok(items)
87}
88
89/// Writes `&[rows]` without changing the rows or their order.
90fn borrowed_slice(rows: Vec<Vec<GeneratedToken>>) -> Result<Vec<GeneratedToken>, Overflow> {
91    Ok(vec![
92        GeneratedToken::alone('&'),
93        group(GeneratedDelimiter::Bracket, comma_many(rows))?,
94    ])
95}