Skip to main content

mollendorff_forge/functions/
registry.rs

1//! Function Registry - Single Source of Truth for all Forge functions
2//!
3//! This module defines all supported functions with metadata including:
4//! - Function name
5//! - Category
6//! - Description
7//! - Syntax
8//! - Demo availability (demo: true = included in demo build)
9//! - Scalar compatibility (scalar: true = works with v1.0.0 schema, no tables needed)
10//!
11//! See ADR-013 for the design rationale.
12//! See ADR-014 for scalar/array classification.
13
14pub use super::definitions::FUNCTIONS;
15
16/// Function category for grouping
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub enum Category {
19    Math,
20    Aggregation,
21    Logical,
22    Text,
23    Date,
24    Lookup,
25    Financial,
26    Statistical,
27    Trigonometric,
28    Information,
29    Conditional,
30    Array,
31    Advanced,
32    ForgeNative,
33    MonteCarlo,
34}
35
36impl std::fmt::Display for Category {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        match self {
39            Self::Math => write!(f, "Math"),
40            Self::Aggregation => write!(f, "Aggregation"),
41            Self::Logical => write!(f, "Logical"),
42            Self::Text => write!(f, "Text"),
43            Self::Date => write!(f, "Date"),
44            Self::Lookup => write!(f, "Lookup"),
45            Self::Financial => write!(f, "Financial"),
46            Self::Statistical => write!(f, "Statistical"),
47            Self::Trigonometric => write!(f, "Trigonometric"),
48            Self::Information => write!(f, "Information"),
49            Self::Conditional => write!(f, "Conditional"),
50            Self::Array => write!(f, "Array"),
51            Self::Advanced => write!(f, "Advanced"),
52            Self::ForgeNative => write!(f, "Forge Native"),
53            Self::MonteCarlo => write!(f, "Monte Carlo"),
54        }
55    }
56}
57
58/// Function definition with all metadata
59#[derive(Debug, Clone)]
60pub struct FunctionDef {
61    /// Function name (e.g., "SUM")
62    pub name: &'static str,
63    /// Category for grouping
64    pub category: Category,
65    /// Short description
66    pub description: &'static str,
67    /// Usage syntax (e.g., "=SUM(value1, value2, ...)")
68    pub syntax: &'static str,
69    /// Available in demo build (false = enterprise only)
70    pub demo: bool,
71    /// Scalar compatible (true = works with v1.0.0 schema without tables/arrays)
72    /// scalar=true: single value in, single value out (e.g., ABS, SQRT, IF)
73    /// scalar=false: requires table/array context (e.g., UNIQUE, FILTER, SUMIF)
74    pub scalar: bool,
75}
76
77/// Get demo functions only
78pub fn demo_functions() -> impl Iterator<Item = &'static FunctionDef> {
79    FUNCTIONS.iter().filter(|f| f.demo)
80}
81
82/// Get enterprise functions (all)
83pub fn enterprise_functions() -> impl Iterator<Item = &'static FunctionDef> {
84    FUNCTIONS.iter()
85}
86
87/// Count demo functions
88#[must_use]
89pub fn count_demo() -> usize {
90    FUNCTIONS.iter().filter(|f| f.demo).count()
91}
92
93/// Count enterprise functions (total)
94#[must_use]
95pub fn count_enterprise() -> usize {
96    FUNCTIONS.len()
97}
98
99/// Get functions by category
100pub fn by_category(category: Category) -> impl Iterator<Item = &'static FunctionDef> {
101    FUNCTIONS.iter().filter(move |f| f.category == category)
102}
103
104/// Get demo functions by category
105pub fn demo_by_category(category: Category) -> impl Iterator<Item = &'static FunctionDef> {
106    FUNCTIONS
107        .iter()
108        .filter(move |f| f.demo && f.category == category)
109}
110
111/// Check if function is available in demo build
112#[must_use]
113pub fn is_demo_function(name: &str) -> bool {
114    FUNCTIONS.iter().any(|f| f.name == name && f.demo)
115}
116
117/// Find function by name
118#[must_use]
119pub fn find_function(name: &str) -> Option<&'static FunctionDef> {
120    FUNCTIONS.iter().find(|f| f.name == name)
121}
122
123/// Count scalar functions (v1.0.0 compatible)
124#[must_use]
125pub fn count_scalar() -> usize {
126    FUNCTIONS.iter().filter(|f| f.scalar).count()
127}
128
129/// Count array-only functions (v5.0.0 only)
130#[must_use]
131pub fn count_array_only() -> usize {
132    FUNCTIONS.iter().filter(|f| !f.scalar).count()
133}
134
135/// Get scalar functions only
136pub fn scalar_functions() -> impl Iterator<Item = &'static FunctionDef> {
137    FUNCTIONS.iter().filter(|f| f.scalar)
138}
139
140/// Get array-only functions
141pub fn array_only_functions() -> impl Iterator<Item = &'static FunctionDef> {
142    FUNCTIONS.iter().filter(|f| !f.scalar)
143}
144
145// Tests moved to registry_tests.rs to keep this file under 1500 lines