fsvalidator 0.1.3

A file structure validator
Documentation
fsvalidator-0.1.3 has been yanked.

File Structure Validator (fsvalidator)

A Rust library for validating real filesystem directories against a declarative, strongly-typed schema. Useful for enforcing project structure, data ingestion layout, or configuration rules.

Crates.io Documentation

Features

  • Flexible Matching: Validate files and directories using both literal names and regex patterns
  • Nested Hierarchies: Support for complex directory trees with arbitrary depth
  • Template System: Reuse common structures via a template reference system
  • Strictness Controls: Fine-grained control over validation strictness (required files, restricted directories)
  • Format Options: Define validation rules in TOML or JSON formats
  • Descriptive Errors: Clear, informative error messages for validation failures

Installation

Add to your Cargo.toml:

[dependencies]
fsvalidator = { version = "0.1.3", features = ["toml"] } # or "json" feature

Quick Start

use anyhow::Result;
use fsvalidator::from_toml;

fn main() -> Result<()> {
    // Load structure definition from TOML
    let root = from_toml("path/to/fsvalidator.toml")?;

    // Display the parsed structure (optional)
    println!("{root}");

    // Validate a directory against the defined structure
    root.validate("./path/to/validate")?;

    Ok(())
}

Definition Format

TOML Example

# Root directory definition
[root]
type = "dir"
name = "project"
required = true
allow_defined_only = true

# Define children of the root directory
[[root.children]]
type = "file"
name = "README.md"
required = true

[[root.children]]
type = "dir"
name = "src"
required = true

# Define children of the src directory
[[root.children.children]]
type = "file"
pattern = ".*\.rs"
required = true

# Reference to a template
[[root.children]]
type = "ref"
name = "tests"
ref = "test_directory"

# Template definition
[template.test_directory]
type = "dir"
name = "tests"
required = false

[[template.test_directory.children]]
type = "file"
pattern = "test_.*\.rs"
required = false

# Global settings (applied to all nodes unless overridden)
[global]
required = false
allow_defined_only = false

JSON Example

{
  "root": {
    "type": "dir",
    "name": "project",
    "required": true,
    "allow_defined_only": true,
    "children": [
      {
        "type": "file",
        "name": "README.md",
        "required": true
      },
      {
        "type": "dir",
        "name": "src",
        "required": true,
        "children": [
          {
            "type": "file",
            "pattern": ".*\.rs",
            "required": true
          }
        ]
      },
      {
        "type": "ref",
        "name": "tests",
        "ref": "test_directory"
      }
    ]
  },
  "template": {
    "test_directory": {
      "type": "dir",
      "name": "tests",
      "required": false,
      "children": [
        {
          "type": "file",
          "pattern": "test_.*\.rs",
          "required": false
        }
      ]
    }
  },
  "global": {
    "required": false,
    "allow_defined_only": false
  }
}

Definition Structure

Node Types

  • dir: A directory node
  • file: A file node
  • ref: A reference to a template

Node Properties

  • name: Literal name of the file or directory
  • pattern: Regex pattern to match against file or directory name (use either name or pattern, not both)
  • required: Whether the node must exist (default: false)
  • allow_defined_only: For directories, whether only defined children are allowed (default: false)
  • children: List of child nodes (only valid for dir type)
  • ref: Template reference name (only valid for ref type)

Special Sections

  • root: The root node of the validation tree
  • template: Dictionary of reusable node templates
  • global: Global settings applied to all nodes unless overridden
  • config: Configuration options for the validator

Model Structure

// Main node types
enum Node {
    Dir(Rc<RefCell<DirNode>>),
    File(Rc<RefCell<FileNode>>),
}

// Directory node with children
struct DirNode {
    name: NodeName,
    children: Vec<Node>,
    required: bool,
    allow_defined_only: bool,
}

// File node
struct FileNode {
    name: NodeName,
    required: bool,
}

// Node name (literal or pattern)
enum NodeName {
    Literal(String),
    Pattern(String), // Regex pattern
}

Use Cases

  • Enforcing consistent project layouts
  • Validating data pipeline inputs/outputs
  • Ensuring configuration directories are correctly structured
  • Verifying deployment artifacts
  • Testing file-based APIs

Advanced Usage

Programmatic Structure Creation

You can create validation structures programmatically:

use fsvalidator::model::{DirNode, FileNode, Node, NodeName};

// Create a file node
let readme = FileNode::new(NodeName::Literal("README.md".to_string()), true);

// Create a directory with pattern-matched files
let src_files = FileNode::new(NodeName::Pattern(".*\.rs".to_string()), true);
let src_dir = DirNode::new(
    NodeName::Literal("src".to_string()),
    vec![src_files],
    true,
    false
);

// Create the project root
let project = DirNode::new(
    NodeName::Literal("project".to_string()),
    vec![readme, src_dir],
    true,
    true
);

// Validate a directory
project.validate("path/to/project").expect("Validation failed");

License

MIT OR Apache-2.0