mathhook_core/formatter/
latex.rs

1use super::{FormattingContext, FormattingError};
2use crate::core::Expression;
3
4mod expressions;
5mod functions;
6
7const MAX_RECURSION_DEPTH: usize = 1000;
8const MAX_TERMS_PER_OPERATION: usize = 10000;
9
10/// LaTeX formatting context
11#[derive(Debug, Default, Clone)]
12pub struct LaTeXContext {
13    pub needs_parentheses: bool,
14}
15
16impl FormattingContext for LaTeXContext {}
17
18/// Format the expression to LaTeX
19pub trait LaTeXFormatter {
20    /// Format an Expression as LaTeX mathematical notation
21    ///
22    /// Converts mathematical expressions into LaTeX format suitable for
23    /// rendering in mathematical documents and publications.
24    ///
25    /// # Arguments
26    /// * `context` - LaTeX formatting configuration
27    ///
28    /// # Context Options
29    /// * `needs_parentheses` - Whether to wrap the entire expression in parentheses
30    ///
31    /// # Examples
32    /// ```
33    /// use mathhook_core::{Expression, expr};
34    /// use mathhook_core::formatter::latex::{LaTeXFormatter, LaTeXContext};
35    ///
36    /// let expression = expr!(x ^ 2);
37    /// let context = LaTeXContext::default();
38    /// let result = expression.to_latex(context).unwrap();
39    /// assert!(result.contains("x"));
40    /// assert!(result.contains("2"));
41    /// ```
42    ///
43    /// # Error Handling
44    /// Returns error messages for expressions that exceed safety limits:
45    /// - Maximum recursion depth (1000 levels)
46    /// - Maximum terms per operation (10000 terms)
47    fn to_latex<C>(&self, context: C) -> Result<String, FormattingError>
48    where
49        C: Into<Option<LaTeXContext>>,
50    {
51        let context = context.into().unwrap_or_default();
52        self.to_latex_with_depth(&context, 0)
53    }
54
55    /// Format with explicit recursion depth tracking
56    ///
57    /// Internal method that provides stack overflow protection by tracking
58    /// recursion depth. This method returns a Result to allow proper error
59    /// propagation during recursive formatting.
60    ///
61    /// # Arguments
62    /// * `context` - LaTeX formatting configuration
63    /// * `depth` - Current recursion depth (starts at 0)
64    ///
65    /// # Returns
66    /// * `Ok(String)` - Successfully formatted LaTeX expression
67    /// * `Err(String)` - Error message if limits exceeded
68    ///
69    /// # Safety Limits
70    /// * Maximum recursion depth: 1000 levels
71    /// * Maximum terms per operation: 10000 terms/factors/arguments
72    fn to_latex_with_depth(
73        &self,
74        context: &LaTeXContext,
75        depth: usize,
76    ) -> Result<String, FormattingError>;
77
78    /// Convert function to LaTeX with context and depth tracking
79    fn function_to_latex_with_depth(
80        &self,
81        name: &str,
82        args: &[Expression],
83        context: &LaTeXContext,
84        depth: usize,
85    ) -> Result<String, FormattingError>;
86
87    /// Convert function to LaTeX (convenience method)
88    fn function_to_latex(
89        &self,
90        name: &str,
91        args: &[Expression],
92        context: &LaTeXContext,
93    ) -> Result<String, FormattingError> {
94        match self.function_to_latex_with_depth(name, args, context, 0) {
95            Ok(result) => Ok(result),
96            Err(error) => Err(FormattingError::InvalidMathConstruct {
97                reason: error.to_string(),
98            }),
99        }
100    }
101}
102
103impl LaTeXFormatter for Expression {
104    fn to_latex_with_depth(
105        &self,
106        context: &LaTeXContext,
107        depth: usize,
108    ) -> Result<String, FormattingError> {
109        expressions::to_latex_with_depth_impl(self, context, depth)
110    }
111
112    fn function_to_latex_with_depth(
113        &self,
114        name: &str,
115        args: &[Expression],
116        context: &LaTeXContext,
117        depth: usize,
118    ) -> Result<String, FormattingError> {
119        functions::function_to_latex_with_depth_impl(self, name, args, context, depth)
120    }
121}