| Crates.io | genfile_core |
| lib.rs | genfile_core |
| version | 0.9.0 |
| created_at | 2025-10-21 06:23:07.872816+00 |
| updated_at | 2026-01-23 08:58:49.920638+00 |
| description | File generation tools for code generation and template materialization. |
| homepage | https://github.com/Wandalen/wTools/tree/master/module/core/genfile_core |
| repository | https://github.com/Wandalen/wTools/tree/master/module/core/genfile_core |
| max_upload_size | |
| id | 1893338 |
| size | 362,790 |
A trait-based template processing and file generation library for Rust. genfile provides self-contained template archives with parameter storage, pluggable rendering engines, and testable in-memory file systems.
MemoryFileSystem for fast, isolated testing without disk I/OFileRef and UrlRef with custom resolvers and storage backendsAdd to your Cargo.toml:
[dependencies]
genfile_core = "0.1"
use genfile_core::{ TemplateArchive, WriteMode, Value, MemoryFileSystem, HandlebarsRenderer, FileSystem };
use std::path::{ Path, PathBuf };
// Create a template archive
let mut archive = TemplateArchive::new( "my-project" );
// Add template files
archive.add_text_file(
PathBuf::from( "README.md" ),
"# {{project_name}}\n\n{{description}}",
WriteMode::Rewrite
);
archive.add_text_file(
PathBuf::from( "src/main.rs" ),
"fn main() {\n println!(\"Hello from {{project_name}}!\");\n}",
WriteMode::Rewrite
);
// Set parameter values
archive.set_value( "project_name", Value::String( "MyApp".into() ) );
archive.set_value( "description", Value::String( "A cool application".into() ) );
// Materialize to memory filesystem (for testing)
let renderer = HandlebarsRenderer::new();
let mut fs = MemoryFileSystem::new();
archive.materialize_with_components(
Path::new( "/output" ),
&renderer,
&mut fs
).unwrap();
// Verify generated files
assert!( fs.exists( &PathBuf::from( "/output/README.md" ) ) );
assert_eq!(
fs.read( &PathBuf::from( "/output/README.md" ) ).unwrap(),
"# MyApp\n\nA cool application"
);
use genfile_core::{ TemplateArchive, FileContent, WriteMode, Value };
use std::path::PathBuf;
let mut archive = TemplateArchive::new( "website" );
// Text template
archive.add_text_file(
PathBuf::from( "index.html" ),
"<html><title>{{title}}</title></html>",
WriteMode::Rewrite
);
// Binary file (PNG header)
archive.add_binary_file(
PathBuf::from( "logo.png" ),
vec![ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ]
);
archive.set_value( "title", Value::String( "My Site".into() ) );
use genfile_core::TemplateArchive;
// Create and serialize to JSON
let archive = TemplateArchive::new( "config" );
let json = archive.to_json_pretty().unwrap();
// Save to file
std::fs::write( "template.json", json ).unwrap();
// Load from file
let json = std::fs::read_to_string( "template.json" ).unwrap();
let restored = TemplateArchive::from_json( &json ).unwrap();
use genfile_core::{ TemplateArchive, FileRef, UrlRef, WriteMode };
use std::path::PathBuf;
let mut archive = TemplateArchive::new( "docs" );
// Reference external file
archive.add_file_from(
PathBuf::from( "header.txt" ),
FileRef::new( PathBuf::from( "/templates/header.hbs" ) ),
WriteMode::Rewrite
);
// Reference URL
archive.add_file_from(
PathBuf::from( "footer.txt" ),
UrlRef::new( "https://example.com/templates/footer.hbs" ),
WriteMode::Rewrite
);
use genfile_core::{ TemplateArchive, ContentStorage, FileContent, HandlebarsRenderer };
use std::path::Path;
struct CloudStorage;
impl ContentStorage for CloudStorage
{
fn store( &mut self, path: &Path, content: &FileContent ) -> Result< (), genfile_core::Error >
{
// Upload to S3, Azure, etc.
println!( "Uploading {} to cloud", path.display() );
Ok( () )
}
}
use genfile_core::{ TemplateArchive, ParameterDescriptor, WriteMode };
use std::path::PathBuf;
let mut archive = TemplateArchive::new( "app" );
archive.add_text_file(
PathBuf::from( "config.txt" ),
"App: {{app_name}}",
WriteMode::Rewrite
);
// Add parameter definitions
archive.add_parameter( ParameterDescriptor
{
parameter: "app_name".into(),
is_mandatory: true,
default_value: None,
description: Some( "Application name".into() ),
});
// Discover parameters used in templates
let discovered = archive.discover_parameters();
// Analyze parameter usage
let usage = archive.analyze_parameter_usage();
// Find undefined parameters
let undefined = archive.get_undefined_parameters();
TemplateArchive - Main entity for template operations, stores files, parameters, and valuesTemplate<V,R> - Alternative API with custom value types and renderersTemplateFile - Individual file with content, metadata, and optional external sourceFileContent - Enum for Text(String) or Binary(Vec<u8>)Value - Default parameter value type: String, Number, Bool, ListTemplateValue - Trait for custom parameter value typesTemplateRenderer - Trait for pluggable rendering engines (default: Handlebars)FileSystem - Trait for file operations (RealFileSystem or MemoryFileSystem)ContentResolver - Trait for resolving external content sourcesContentStorage - Trait for custom storage backendsContentSource::Inline - Content embedded directly in archiveContentSource::File - Reference to external file pathContentSource::Url - Reference to remote URLAll file paths are validated to prevent directory traversal attacks:
use genfile_core::validate_path;
use std::path::Path;
// Valid paths
assert!( validate_path( Path::new( "src/lib.rs" ) ).is_ok() );
assert!( validate_path( Path::new( "./foo/bar.txt" ) ).is_ok() );
// Invalid paths (rejected)
assert!( validate_path( Path::new( "../etc/passwd" ) ).is_err() );
assert!( validate_path( Path::new( "foo/../../bar" ) ).is_err() );
27 dedicated security tests ensure protection against malicious paths.
Use MemoryFileSystem for fast, isolated tests:
use genfile_core::{ TemplateArchive, MemoryFileSystem, HandlebarsRenderer, FileSystem };
use std::path::Path;
#[ test ]
fn test_generation()
{
let archive = TemplateArchive::new( "test" );
let renderer = HandlebarsRenderer::new();
let mut fs = MemoryFileSystem::new();
// No disk I/O - runs in memory
archive.materialize_with_components(
Path::new( "/output" ),
&renderer,
&mut fs
).unwrap();
// Fast assertions
assert!( fs.exists( Path::new( "/output/README.md" ) ) );
}