textfsm-core 0.2.0

Core parsing library for TextFSM template-based state machine
Documentation
# textfsm-rust

A Rust implementation of Google's [TextFSM](https://github.com/google/textfsm) template-based state machine for parsing semi-formatted text.

## Overview

TextFSM is a template-based state machine originally developed by Google for parsing CLI output from network devices. This crate provides a native Rust implementation with the same template syntax and behavior.

## Features

- **Battle-tested compatibility** - 99.8% pass rate against the [ntc-templates]https://github.com/networktocode/ntc-templates test suite (1633/1637 tests)
- **Compile-time template validation** - Catch template errors at compile time with proc macros, not at runtime
- **Serde integration** - Deserialize parsed results directly into typed Rust structs
- **Thread-safe design** - `Template` is `Send + Sync`; share compiled templates across threads with zero overhead
- **Detailed error messages** - Template errors include line numbers, context, and suggestions
- **Full TextFSM syntax** - All value options (`Required`, `Filldown`, `Fillup`, `List`, `Key`) and actions (`Next`, `Continue`, `Record`, `Clear`, `Error`)
- **Efficient regex handling** - Uses [fancy-regex]https://docs.rs/fancy-regex which delegates to the fast [regex]https://docs.rs/regex crate when advanced features aren't needed
- **Python regex compatibility** - Handles Python regex quirks like `\<` and `\>` automatically

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
textfsm-rust = "0.1"
```

## Quick Start

```rust
use textfsm_rust::Template;

let template = Template::parse_str(r#"
Value Name (\S+)
Value Age (\d+)

Start
  ^Name: ${Name}, Age: ${Age} -> Record
"#)?;

let mut parser = template.parser();
let input = "Name: Alice, Age: 30\nName: Bob, Age: 25\n";
let results = parser.parse_text(input)?;
```

## Compile-Time Template Validation

Catch template errors before your program runs:

```rust
use textfsm_rust::{validate_template, validate_templates, Template};

// Validate a single template at compile time
validate_template!("templates/cisco_show_version.textfsm");

// Validate all .textfsm files in a directory
validate_templates!("templates/");

// Parse at runtime when you need it
let template = Template::parse_str(
    include_str!("templates/cisco_show_version.textfsm")
).expect("validated at compile time");
```

If a template is invalid, you get a compile error with the template line number:

```
error: Template validation failed for 'templates/bad.textfsm':
       invalid variable substitution at line 8: unknown variable 'Interfce'
 --> src/main.rs:4:21
  |
4 | validate_template!("templates/bad.textfsm");
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^
```

## Template Syntax

TextFSM templates consist of two sections:

### Value Definitions

```
Value [Options] Name (Regex)
```

Options:
- `Required` - Record only saved if this value is matched
- `Filldown` - Value retained across records
- `Fillup` - Value fills upward into previous records
- `List` - Value is a list of matches
- `Key` - Marks value as a key field

### State Rules

```
StateName
  ^Regex -> [Actions]
```

Actions:
- `Next` - Continue to next line (default)
- `Continue` - Continue processing current line
- `Record` - Save current record
- `Clear` - Clear non-filldown values
- `Error` - Stop processing with error

## Serde Integration

Enable the `serde` feature to deserialize parsed results directly into typed Rust structs:

```toml
[dependencies]
textfsm-rust = { version = "0.1", features = ["serde"] }
```

```rust
use textfsm_rust::{Deserialize, Template};

#[derive(Deserialize, Debug)]
struct Interface {
    interface: String,
    status: String,
    ip_address: Option<String>,
}

let template = Template::parse_str(r#"
Value Interface (\S+)
Value Status (up|down)
Value IP_Address (\d+\.\d+\.\d+\.\d+)

Start
  ^Interface: ${Interface} is ${Status}
  ^  IP: ${IP_Address} -> Record
"#)?;

let mut parser = template.parser();
let input = "Interface: eth0 is up\n  IP: 192.168.1.1\nInterface: eth1 is down\n  IP: 10.0.0.1\n";

// Deserialize directly into typed structs
let interfaces: Vec<Interface> = parser.parse_text_into(input)?;

assert_eq!(interfaces[0].interface, "eth0");
assert_eq!(interfaces[0].status, "up");
assert_eq!(interfaces[0].ip_address, Some("192.168.1.1".into()));
```

Field names are matched case-insensitively against template value names (underscores are preserved).

## Thread Safety

`Template` is `Send + Sync` and can be safely shared across threads. The compiled template (including all regexes) is immutable after creation, so you can wrap it in an `Arc` and share it freely.

`Parser` is a lightweight, stateful wrapper that borrows a `Template`. Create one per thread - they're cheap since they don't copy the compiled regexes.

```rust
use std::sync::Arc;
use std::thread;

let template = Arc::new(Template::parse_str(template_str)?);

let handles: Vec<_> = inputs.into_iter().map(|input| {
    let template = Arc::clone(&template);
    thread::spawn(move || {
        let mut parser = template.parser();
        parser.parse_text(&input)
    })
}).collect();
```

This design is efficient for concurrent workloads like parsing output from multiple network devices in parallel.

## Error Messages

Template errors include line numbers to help you fix issues quickly:

```
invalid variable substitution at line 8: unknown variable 'Interfce'
```

```
invalid Value definition at line 3: regex must be wrapped in parentheses
```

```
invalid rule at line 12: unclosed variable substitution
```

```
missing required 'Start' state
```

## Roadmap

- [x] Full TextFSM syntax compatibility
- [x] Tested against ntc-templates (99.8% pass rate)
- [x] Thread-safe template sharing
- [x] Compile-time template validation macros
- [x] Serde deserialization for parsed results
- [ ] CliTable - index-based template selection by command/platform (like [Python's CliTable](https://github.com/google/textfsm/wiki/Cli-Table))
- [ ] Template linting and suggestions
- [ ] Performance benchmarks vs Python implementation

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

## Acknowledgments

This project is a Rust port of [Google's TextFSM](https://github.com/google/textfsm), originally developed by Google Inc. and licensed under Apache 2.0.