MultiTemplate

Struct MultiTemplate 

Source
pub struct MultiTemplate { /* private fields */ }
Expand description

A template engine supporting mixed literal text and string transformation operations.

MultiTemplate can contain any combination of literal text sections and template sections that apply string operations to input data. This enables creating complex text formatting patterns while maintaining high performance through intelligent caching.

§Template Structure

Templates are parsed into sections:

  • Literal sections: Static text that appears unchanged in output
  • Template sections: Operation sequences in {op1|op2|...} format

§Caching Strategy

The template engine employs multiple levels of caching:

  • Split cache: Common string splitting operations are cached globally
  • Regex cache: Compiled regex patterns are cached for reuse
  • Operation cache: Results of template sections are cached per input hash

§Debug Support

When debug mode is enabled, templates provide detailed execution tracing:

  • Section-by-section processing breakdown
  • Operation timing and cache statistics
  • Input/output transformations

§Examples

§Basic Template Usage

use string_pipeline::Template;

let template = Template::parse("Result: {upper|trim}").unwrap();
assert_eq!(template.format("  hello  ").unwrap(), "Result: HELLO");

§Multi-Section Templates

use string_pipeline::Template;

let template = Template::parse("User: {split: :0} ({split: :1})").unwrap();
assert_eq!(template.format("john smith").unwrap(), "User: john (smith)");

§Debug Mode

use string_pipeline::Template;

let template = Template::parse_with_debug("{split:,:..|sort|join: \\| }", Some(true)).unwrap();
let result = template.format("c,a,b").unwrap(); // Prints debug info to stderr
assert_eq!(result, "a | b | c");

Implementations§

Source§

impl MultiTemplate

Source

pub fn parse(template: &str) -> Result<Self, String>

Parse a template string into a MultiTemplate instance.

Parses template syntax containing literal text and {operation} blocks, with support for complex operation pipelines, debug information is suppressed.

§Arguments
  • template - The template string to parse
§Returns
  • Ok(MultiTemplate) - Successfully parsed template
  • Err(String) - Parse error description
§Template Syntax
  • Literal text appears as-is in output
  • {operation} blocks apply transformations to input
  • Multiple operations: {op1|op2|op3}
  • Debug markers: {!debug} are suppressed
§Examples
use string_pipeline::Template;

// Simple template
let template = Template::parse("Hello {upper}!").unwrap();

// Complex pipeline
let template = Template::parse("{split:,:..|sort|join: - }").unwrap();
Source

pub fn parse_with_debug( template: &str, debug: Option<bool>, ) -> Result<Self, String>

Parse a template string into a MultiTemplate instance.

Parses template syntax containing literal text and {operation} blocks, with support for complex operation pipelines and debug mode.

§Arguments
  • template - The template string to parse
  • debug - Optional debug mode override (None uses template’s debug markers)
§Returns
  • Ok(MultiTemplate) - Successfully parsed template
  • Err(String) - Parse error description
§Template Syntax
  • Literal text appears as-is in output
  • {operation} blocks apply transformations to input
  • Multiple operations: {op1|op2|op3}
  • Debug markers: {!debug}
§Examples
use string_pipeline::Template;

// Simple template
let template = Template::parse_with_debug("Hello {upper}!", None).unwrap();

// Complex pipeline
let template = Template::parse_with_debug("{split:,:..|sort|join: - }", None).unwrap();

// Debug enabled
let template = Template::parse_with_debug("{!upper|trim}", None).unwrap();

// Debug override
let template = Template::parse_with_debug("{upper}", Some(true)).unwrap();
Source

pub fn format(&self, input: &str) -> Result<String, String>

Apply the template to input data, producing formatted output.

Processes each template section in sequence, applying literal text directly and executing operation pipelines on the input data. Results are cached per input to optimize repeated operations.

§Arguments
  • input - The input string to transform
§Returns
  • Ok(String) - The formatted result
  • Err(String) - Error description if processing fails
§Performance
  • Template sections with identical operations and input are cached
  • Single split operations use a fast path
  • Common separators are interned to reduce allocations
  • ASCII-only operations use optimized algorithms where possible
§Debug Output

When debug mode is enabled, detailed execution information is printed to stderr:

  • Section-by-section processing
  • Operation timing and cache statistics
  • Input/output transformations
§Examples
use string_pipeline::Template;

let template = Template::parse("Name: {split: :0}, Age: {split: :1}").unwrap();
let result = template.format("John 25").unwrap();
assert_eq!(result, "Name: John, Age: 25");

// List processing
let template = Template::parse("Items: {split:,:..|sort|join: \\| }").unwrap();
let result = template.format("apple,banana,cherry").unwrap();
assert_eq!(result, "Items: apple | banana | cherry");
Source

pub fn template_string(&self) -> &str

Get the original template string.

Returns the raw template string that was used to create this instance, useful for debugging, serialization, or displaying template definitions.

§Examples
use string_pipeline::Template;

let template = Template::parse("Hello {upper}!").unwrap();
assert_eq!(template.template_string(), "Hello {upper}!");
Source

pub fn section_count(&self) -> usize

Get the total number of sections in the template.

Returns the count of all sections (both literal and template sections) that make up this template.

§Examples
use string_pipeline::Template;

let template = Template::parse("Hello {upper} world!").unwrap();
assert_eq!(template.section_count(), 3); // "Hello ", "{upper}", " world!"
Source

pub fn template_section_count(&self) -> usize

Get the number of template sections (excluding literals).

Returns the count of sections that contain operations, excluding literal text sections.

§Examples
use string_pipeline::Template;

let template = Template::parse("Hello {upper} world {lower}!").unwrap();
assert_eq!(template.template_section_count(), 2); // {upper} and {lower}
Source

pub fn is_debug(&self) -> bool

Check if debug mode is enabled.

Returns true if this template will output debug information during formatting operations.

§Examples
use string_pipeline::Template;

let template = Template::parse_with_debug("{upper}", Some(true)).unwrap();
assert!(template.is_debug());
Source

pub fn with_debug(self, debug: bool) -> Self

Create a new template instance with debug mode set.

Returns a new template with the specified debug setting, leaving the original unchanged.

§Arguments
  • debug - Whether to enable debug mode
Source

pub fn set_debug(&mut self, debug: bool)

Set debug mode on this template instance.

Modifies this template’s debug setting in place.

§Arguments
  • debug - Whether to enable debug mode
§Examples
use string_pipeline::Template;

let mut template = Template::parse("{upper}").unwrap();
template.set_debug(true);
assert!(template.is_debug());
Source

pub fn format_with_inputs( &self, inputs: &[&[&str]], separators: &[&str], ) -> Result<String, String>

Format template with multiple inputs per template section.

This method enables advanced template processing where each template section can receive multiple input values that are joined with individual separators. This is useful for complex formatting scenarios like batch processing or command construction where different template sections need different data.

§Arguments
  • inputs - Slice of input slices, where each inner slice contains the inputs for one template section
  • separators - Slice of separators, one for each template section to join multiple inputs
§Returns
  • Ok(String) - The formatted result with each template section processed with its joined inputs
  • Err(String) - Error if template section processing fails
§Input/Template/Separator Count Handling

This method gracefully handles mismatches between counts:

  • Excess inputs: Extra inputs beyond template section count are truncated/ignored
  • Insufficient inputs: Missing inputs are treated as empty strings for remaining template sections
  • Excess separators: Extra separators beyond template section count are truncated/ignored
  • Insufficient separators: Missing separators default to space “ “ for remaining template sections
§Template Section Ordering

Template sections are numbered from left to right, starting at 0. Literal sections are not counted. For example, in "Hello {upper} world {lower}!":

  • Template section 0: {upper}
  • Template section 1: {lower}
  • Total template sections: 2
§Input Processing

For each template section:

  • Empty slice []: Uses empty string as input
  • Single item ["value"]: Uses “value” directly as input
  • Multiple items ["a", "b", "c"]: Joins with corresponding separator
§Examples
use string_pipeline::Template;

// Multiple inputs for first section, single input for second
let template = Template::parse("Users: {upper} | Email: {lower}").unwrap();
let result = template.format_with_inputs(&[
    &["john doe", "peter parker"],
    &["ADMIN@EXAMPLE.COM"],
], &[" ", " "]).unwrap();
assert_eq!(result, "Users: JOHN DOE PETER PARKER | Email: admin@example.com");

// Excess inputs are truncated
let template = Template::parse("diff {} {}").unwrap();
let result = template.format_with_inputs(&[
    &["file1.txt"],
    &["file2.txt"],
    &["file3.txt"], // This will be ignored
], &[" ", " "]).unwrap();
assert_eq!(result, "diff file1.txt file2.txt");

// Insufficient inputs use empty strings
let template = Template::parse("cmd {} {} {}").unwrap();
let result = template.format_with_inputs(&[
    &["arg1"],
    &["arg2"],
    // Missing third input - will use empty string
], &[" ", " ", " "]).unwrap();
assert_eq!(result, "cmd arg1 arg2 ");

// Insufficient separators default to space
let template = Template::parse("files: {} more: {}").unwrap();
let result = template.format_with_inputs(&[
    &["a", "b", "c"],
    &["x", "y", "z"],
], &[","]).unwrap(); // Only one separator provided
assert_eq!(result, "files: a,b,c more: x y z"); // Second uses default space
Source

pub fn get_template_sections(&self) -> Vec<(usize, &Vec<StringOp>)>

Get information about template sections for introspection.

Returns a vector of tuples containing the position and operations for each template section in the template. This is useful for understanding the structure of a template before processing it with format_with_inputs.

§Returns

A vector where each element is a tuple of:

  • usize - The position/index of the template section (0-based)
  • &Vec<StringOp> - Reference to the operations in that section
§Examples
use string_pipeline::Template;

let template = Template::parse("Hello {upper} world {lower|trim}!").unwrap();
let sections = template.get_template_sections();

assert_eq!(sections.len(), 2);
assert_eq!(sections[0].0, 0); // First template section at position 0
assert_eq!(sections[1].0, 1); // Second template section at position 1
assert_eq!(sections[0].1.len(), 1); // {upper} has 1 operation
assert_eq!(sections[1].1.len(), 2); // {lower|trim} has 2 operations
Source

pub fn get_section_info(&self) -> Vec<SectionInfo>

Get detailed information about all sections in the template.

Returns information about both literal and template sections, including their types, positions, and content. This provides a complete view of the template structure for debugging and introspection.

§Returns

A vector of section information structs containing:

  • Section type (literal or template)
  • Position within all sections
  • Content or operation details
§Examples
use string_pipeline::Template;

let template = Template::parse("Hello {upper} world!").unwrap();
let info = template.get_section_info();

assert_eq!(info.len(), 3);
// info[0]: Literal("Hello ")
// info[1]: Template(position=0, operations=[Upper])
// info[2]: Literal(" world!")

Trait Implementations§

Source§

impl Clone for MultiTemplate

Source§

fn clone(&self) -> MultiTemplate

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MultiTemplate

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for MultiTemplate

Provides string representation of the template.

Returns the original template string, making it easy to display or serialize template definitions.

§Examples

use string_pipeline::Template;

let template = Template::parse("Hello {upper}!").unwrap();
println!("{}", template); // Prints: Hello {upper}!
Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.