Contributing
Contributing to FHIRPath Rust Engine
Section titled “Contributing to FHIRPath Rust Engine”Thank you for your interest in contributing to the FHIRPath Rust Engine! This document provides guidelines and information for contributors.
Table of Contents
Section titled “Table of Contents”- Getting Started
- Development Setup
- Project Structure
- Coding Standards
- Testing Guidelines
- Submitting Changes
- Security Considerations
- Performance Guidelines
Getting Started
Section titled “Getting Started”Prerequisites
Section titled “Prerequisites”- Rust 1.70+ (latest stable recommended)
- Node.js 20+ (for Node.js bindings development)
- Git
Quick Start
Section titled “Quick Start”- Fork the repository
- Clone your fork:
git clone https://github.com/yourusername/fhirpath-rs.git
- Create a feature branch:
git checkout -b feature/your-feature-name
- Make your changes
- Run tests:
cargo test --workspace
- Submit a pull request
Development Setup
Section titled “Development Setup”Initial Setup
Section titled “Initial Setup”# Clone the repositorygit clone https://github.com/yourusername/fhirpath-rs.gitcd fhirpath-rs
# Install Rust dependenciescargo build
# Install Node.js dependencies (for Node.js bindings)cd fhirpath-nodenpm installcd ..
# Run all testscargo test --workspacecd fhirpath-node && npm test && cd ..
Development Tools
Section titled “Development Tools”We recommend using the following tools:
- IDE: VS Code with rust-analyzer extension
- Formatting:
rustfmt
(configured inrustfmt.toml
) - Linting:
clippy
(configured inclippy.toml
) - Testing:
cargo test
andcargo nextest
(if available)
Environment Setup
Section titled “Environment Setup”# Install additional development toolscargo install cargo-nextest # For parallel test executioncargo install cargo-watch # For continuous testing during developmentcargo install cargo-audit # For security auditing
# Set up pre-commit hooks (optional but recommended)cargo install pre-commitpre-commit install
Project Structure
Section titled “Project Structure”fhirpath-rs/├── fhirpath-core/ # Core FHIRPath engine implementation│ ├── src/│ │ ├── lexer.rs # Tokenization│ │ ├── parser.rs # AST parsing│ │ ├── evaluator.rs # Expression evaluation│ │ ├── model.rs # Data models│ │ └── errors.rs # Error types│ ├── tests/ # Unit and integration tests│ └── benches/ # Performance benchmarks├── fhirpath-node/ # Node.js bindings│ ├── src/lib.rs # NAPI bindings│ └── test/ # Node.js tests├── fhirpath-cli/ # Command-line interface│ └── src/main.rs # CLI implementation├── docs/ # Documentation└── phases/ # Implementation tracking
Key Components
Section titled “Key Components”- Lexer: Tokenizes FHIRPath expressions
- Parser: Builds Abstract Syntax Tree (AST)
- Evaluator: Executes expressions against FHIR resources
- Model: Defines FHIRPath value types
- Bindings: Node.js integration layer
Coding Standards
Section titled “Coding Standards”Rust Code Style
Section titled “Rust Code Style”We follow standard Rust conventions with some project-specific guidelines:
Formatting
Section titled “Formatting”# Format code before committingcargo fmt --all
# Check formattingcargo fmt --all -- --check
Linting
Section titled “Linting”# Run clippy for lintingcargo clippy --workspace --all-targets --all-features
# Fix clippy warnings where possiblecargo clippy --workspace --all-targets --all-features --fix
Code Organization
Section titled “Code Organization”- Use meaningful names for functions, variables, and types
- Keep functions focused and reasonably sized
- Add comprehensive documentation for public APIs
- Use
#[cfg(test)]
for test-only code - Organize imports: std, external crates, local modules
Documentation
Section titled “Documentation”/// Evaluates a FHIRPath expression against a FHIR resource.////// # Arguments////// * `expression` - The FHIRPath expression to evaluate/// * `resource` - The FHIR resource as JSON////// # Returns////// Returns a `Result` containing the evaluation result or an error.////// # Examples////// ```rust/// use fhirpath_core::evaluator::evaluate_expression;/// use serde_json::json;////// let resource = json!({"resourceType": "Patient", "id": "123"});/// let result = evaluate_expression("id", resource)?;/// ```pub fn evaluate_expression( expression: &str, resource: serde_json::Value,) -> Result<FhirPathValue, FhirPathError> { // Implementation}
Error Handling
Section titled “Error Handling”- Use
Result<T, E>
for fallible operations - Create specific error types for different failure modes
- Provide helpful error messages with context
- Use
anyhow
for application errors, custom types for library errors
use thiserror::Error;
#[derive(Error, Debug)]pub enum FhirPathError { #[error("Parse error: {0}")] ParseError(String),
#[error("Evaluation error: {0}")] EvaluationError(String),
#[error("Type error: {0}")] TypeError(String),}
Testing Guidelines
Section titled “Testing Guidelines”Test Organization
Section titled “Test Organization”- Unit tests: Test individual functions and modules
- Integration tests: Test component interactions
- Conformance tests: Test against FHIRPath specification
- Performance tests: Benchmark critical paths
Writing Tests
Section titled “Writing Tests”#[cfg(test)]mod tests { use super::*; use serde_json::json;
#[test] fn test_basic_property_access() { let resource = json!({ "resourceType": "Patient", "id": "example" });
let result = evaluate_expression("id", resource).unwrap();
match result { FhirPathValue::Collection(values) => { assert_eq!(values.len(), 1); match &values[0] { FhirPathValue::String(s) => assert_eq!(s, "example"), _ => panic!("Expected string value"), } } _ => panic!("Expected collection result"), } }}
Test Data
Section titled “Test Data”- Use realistic FHIR resources for testing
- Store test fixtures in
tests/fixtures/
- Create helper functions for common test scenarios
- Test both success and failure cases
Running Tests
Section titled “Running Tests”# Run all testscargo test --workspace
# Run tests with parallel execution (if nextest is installed)cargo nextest run
# Run specific testcargo test test_basic_property_access
# Run tests with outputcargo test -- --nocapture
# Run benchmarkscargo bench
Submitting Changes
Section titled “Submitting Changes”Pull Request Process
Section titled “Pull Request Process”- Create a feature branch from
main
- Make your changes following coding standards
- Add tests for new functionality
- Update documentation as needed
- Run the full test suite
- Submit a pull request
Pull Request Template
Section titled “Pull Request Template”## DescriptionBrief description of changes
## Type of Change- [ ] Bug fix- [ ] New feature- [ ] Breaking change- [ ] Documentation update
## Testing- [ ] Unit tests added/updated- [ ] Integration tests added/updated- [ ] All tests pass
## Checklist- [ ] Code follows project style guidelines- [ ] Self-review completed- [ ] Documentation updated- [ ] No new warnings introduced
Commit Messages
Section titled “Commit Messages”Use conventional commit format:
type(scope): description
feat(parser): add support for new FHIRPath functionfix(evaluator): handle null values in path expressionsdocs(readme): update installation instructionstest(lexer): add tests for edge cases
Code Review
Section titled “Code Review”- All changes require review before merging
- Address reviewer feedback promptly
- Keep pull requests focused and reasonably sized
- Ensure CI passes before requesting review
Security Considerations
Section titled “Security Considerations”Security Guidelines
Section titled “Security Guidelines”- Input validation: Validate all external inputs
- Resource limits: Prevent resource exhaustion attacks
- Error handling: Don’t leak sensitive information in errors
- Dependencies: Keep dependencies updated and audited
Security Testing
Section titled “Security Testing”# Run security auditcargo audit
# Check for known vulnerabilitiescargo audit --deny warnings
Reporting Security Issues
Section titled “Reporting Security Issues”Please report security vulnerabilities privately to the maintainers rather than creating public issues.
Performance Guidelines
Section titled “Performance Guidelines”Performance Considerations
Section titled “Performance Considerations”- Avoid unnecessary allocations in hot paths
- Use appropriate data structures for the use case
- Profile before optimizing - measure actual performance
- Consider memory usage as well as CPU performance
Benchmarking
Section titled “Benchmarking”# Run benchmarkscargo bench
# Profile with specific toolscargo build --releaseperf record target/release/your-binary
Performance Testing
Section titled “Performance Testing”- Add benchmarks for critical functionality
- Test with realistic data sizes
- Monitor performance regressions in CI
- Document performance characteristics
Development Workflow
Section titled “Development Workflow”Daily Development
Section titled “Daily Development”# Start development sessioncargo watch -x "test --workspace"
# In another terminalcargo watch -x "clippy --workspace"
# Before committingcargo fmt --allcargo clippy --workspace --all-targets --all-featurescargo test --workspace
Release Process
Section titled “Release Process”- Update version numbers in
Cargo.toml
files - Update
CHANGELOG.md
- Run full test suite including benchmarks
- Create release PR
- Tag release after merge
- Publish to crates.io (maintainers only)
Getting Help
Section titled “Getting Help”Resources
Section titled “Resources”- Documentation: Check the
docs/
directory - Examples: See
docs/usage-examples.md
- Tests: Look at existing tests for patterns
- Issues: Search existing issues before creating new ones
Communication
Section titled “Communication”- GitHub Issues: For bugs and feature requests
- GitHub Discussions: For questions and general discussion
- Pull Requests: For code contributions
Maintainer Contact
Section titled “Maintainer Contact”For questions about contributing, reach out to the project maintainers through GitHub issues or discussions.
License
Section titled “License”By contributing to this project, you agree that your contributions will be licensed under the same license as the project (see LICENSE file).
Thank you for contributing to the FHIRPath Rust Engine!