Skip to main content

compile_safe_with_depth

Function compile_safe_with_depth 

Source
pub fn compile_safe_with_depth(
    layout: Box<Layout>,
    max_depth: usize,
) -> Result<Box<Doc>, CompilerError>
Expand description

Compiles a layout with custom recursion depth limit and error handling (configurable safe path)

This function provides the most flexible compilation approach, allowing fine-grained control over stack overflow protection by configuring the maximum recursion depth. It’s useful when you know the characteristics of your layouts and want to optimize for either safety (lower limits) or performance with deeply nested structures (higher limits).

The function uses the same 10-pass compilation pipeline as compile() and compile_safe() but allows customization of the recursion depth threshold that triggers stack overflow protection.

§Arguments

  • layout - The input layout tree to compile. Can handle arbitrarily complex structures within the recursion depth limit.
  • max_depth - Maximum recursion depth before stack overflow protection activates. Must be greater than 0. Common values:
    • Conservative (1,000-5,000): Safe for resource-constrained environments
    • Default (10,000): Good balance of safety and capability
    • Aggressive (20,000+): For known deep layouts with sufficient stack space

§Returns

  • Ok(Box<Doc>) - Successfully compiled document ready for rendering
  • Err(CompilerError) - Compilation failed with detailed error information

§Error Conditions

This function can return several types of errors:

§Performance Notes

  • Time: O(n) where n is the number of layout nodes
  • Memory: Uses 10 temporary bump allocators during compilation
  • Stack Usage: Proportional to layout nesting depth, limited by max_depth
  • Depth Tracking: Minimal overhead for recursion depth counting
  • Optimal Use: When you need precise control over compilation resource usage

§Choosing Recursion Depth Limits

The optimal max_depth depends on your use case:

  • Web Services: 1,000-5,000 (protect against malicious input)
  • Desktop Applications: 10,000-15,000 (balance safety and capability)
  • Code Generators: 20,000+ (handle deeply nested syntax trees)
  • Embedded Systems: 500-2,000 (limited stack space)

§Examples

§Conservative Compilation for Web Services

use typeset::{compile_safe_with_depth, render, text};

fn compile_user_input(content: String) -> Result<String, String> {
    let layout = text(content);
     
    // Use conservative depth limit for untrusted input
    match compile_safe_with_depth(layout, 1000) {
        Ok(doc) => Ok(render(doc, 2, 80)),
        Err(e) => Err(format!("Compilation failed: {}", e)),
    }
}

§High-Performance Compilation for Code Generation

use typeset::{compile_safe_with_depth, render, text, comp, nest};

fn compile_syntax_tree(depth: usize) -> Result<String, String> {
    // Build a deeply nested layout representing a syntax tree
    let mut layout = text("root".to_string());
    for i in 0..depth {
        layout = nest(comp(
            layout,
            text(format!("node_{}", i)),
            false, false
        ));
    }

    // Use high depth limit for known deep structures
    match compile_safe_with_depth(layout, 25000) {
        Ok(doc) => Ok(render(doc, 4, 120)),
        Err(e) => Err(format!("Failed to compile deep tree: {}", e)),
    }
}

§Resource-Constrained Environment

use typeset::{compile_safe_with_depth, render, text, CompilerError};

fn compile_with_limited_stack(layout: Box<typeset::Layout>) -> Result<String, String> {
    // Use very conservative limit for embedded systems
    match compile_safe_with_depth(layout, 500) {
        Ok(doc) => Ok(render(doc, 2, 40)),
        Err(CompilerError::StackOverflow { depth, max_depth }) => {
            Err(format!(
                "Layout too deep for this system: {} levels (max: {})",
                depth, max_depth
            ))
        }
        Err(e) => Err(format!("Compilation error: {}", e)),
    }
}

§Adaptive Depth Strategy

use typeset::{compile_safe_with_depth, render, text, CompilerError};

fn compile_with_fallback(layout: Box<typeset::Layout>) -> Result<String, String> {
    // Try aggressive first, fall back to conservative
    let depths = [20000, 10000, 5000, 1000];
     
    for &depth in &depths {
        match compile_safe_with_depth(layout.clone(), depth) {
            Ok(doc) => return Ok(render(doc, 2, 80)),
            Err(CompilerError::StackOverflow { .. }) => continue,
            Err(e) => return Err(format!("Non-depth error: {}", e)),
        }
    }
     
    Err("Layout too complex even with minimum depth limit".to_string())
}

§Parameter Validation

use typeset::{compile_safe_with_depth, text, CompilerError};

let layout = text("test".to_string());

// This will fail with InvalidInput error
match compile_safe_with_depth(layout, 0) {
    Err(CompilerError::InvalidInput(msg)) => {
        println!("Expected error: {}", msg);
    }
    _ => panic!("Should have failed with InvalidInput"),
}

§See Also

  • compile() - Fast compilation that panics on errors
  • compile_safe() - Safe compilation with default 10,000 depth limit
  • CompilerError - Detailed error types and descriptions
  • render() - Convert compiled documents to strings