Thank you for considering contributing to dfraw_parser! This document provides guidelines to help you contribute effectively.
- Code of Conduct
- How to Contribute
- Development Setup
- Documentation Guidelines
- Coding Standards
- Testing Guidelines
- Pull Request Process
This project follows a standard code of conduct. Please be respectful and constructive in all interactions.
- Check if the issue already exists in the issue tracker
- Use a clear and descriptive title
- Describe the exact steps to reproduce the problem
- Include relevant code samples and error messages
- Specify your environment (OS, Rust version, DF version)
- Use a clear and descriptive title
- Provide a detailed description of the suggested enhancement
- Explain why this enhancement would be useful
- Include code examples if applicable
- Fork the repository
- Create a new branch (
git checkout -b feature/your-feature-name) - Make your changes
- Write or update tests as needed
- Ensure all tests pass
- Update documentation
- Commit your changes with clear commit messages
- Push to your fork
- Open a pull request
- Rust 1.75 or later
- Cargo
- Git
# Clone the repository
git clone https://github.com/nwesterhausen/dfraw_parser.git
cd dfraw_parser
# Build all workspace members
cargo build --workspace
# Run tests
cargo test --workspace
# Check code with clippy
cargo clippy --workspace -- -D warnings# Run all tests
cargo test --workspace
# Run tests for a specific package
cargo test -p dfraw_parser
# Run a specific test
cargo test test_nameGood documentation is crucial for library usability. All public APIs must be documented.
- All public items must have documentation comments (
///or//!) - First line should be a concise summary (aim for < 80 characters)
- Add a blank line before detailed descriptions
- Use proper Markdown formatting
- Include examples for non-trivial functions
Use these sections in order, as appropriate:
/// Brief one-line summary.
///
/// More detailed description if needed. Can span multiple paragraphs.
///
/// # Arguments
///
/// * `param1` - Description of first parameter
/// * `param2` - Description of second parameter
///
/// # Returns
///
/// Description of what is returned
///
/// # Errors
///
/// Description of when and why this function returns an error
///
/// # Panics
///
/// Description of when this function might panic (if applicable)
///
/// # Examples
///
/// ```
/// use dfraw_parser::function_name;
///
/// let result = function_name(arg1, arg2);
/// assert_eq!(result, expected);
/// ```
///
/// # Safety
///
/// (Only for unsafe functions) Explain safety invariants
pub fn function_name(param1: Type1, param2: Type2) -> Result<ReturnType, Error> {
// implementation
}Modules should have documentation explaining their purpose and contents:
//! Brief description of what this module provides.
//!
//! More detailed explanation of the module's purpose and organization.
//!
//! # Examples
//!
//! ```
//! use dfraw_parser::module_name;
//!
//! // Example usage
//! ```
/// Parses a creature definition from a raw file.
///
/// # Arguments
///
/// * `raw_text` - The raw text content to parse
///
/// # Returns
///
/// Returns a `Creature` object or an error if parsing fails.
///
/// # Examples
///
/// ```
/// use dfraw_parser::Creature;
///
/// let raw_text = "[CREATURE:DOG]";
/// let creature = Creature::from_raw(raw_text)?;
/// ```
pub fn from_raw(raw_text: &str) -> Result<Creature, ParserError> {
// implementation
}/// Parses creature
pub fn from_raw(raw_text: &str) -> Result<Creature, ParserError> {
// implementation
}/// Returns the identifier of this creature.
///
/// The identifier is the unique name used in raw files to reference this creature.
///
/// # Examples
///
/// ```
/// # use dfraw_parser::Creature;
/// let creature = Creature::new("DOG");
/// assert_eq!(creature.get_identifier(), "DOG");
/// ```
#[must_use]
pub fn get_identifier(&self) -> &str {
&self.identifier
}/// Represents a parsed creature from Dwarf Fortress raw files.
///
/// A creature definition includes all castes, body parts, behaviors,
/// and other properties defined in the raw files.
#[derive(Debug, Clone)]
pub struct Creature {
/// The unique identifier for this creature
pub identifier: String,
/// Optional description text shown in-game
pub description: Option<String>,
// ... other fields
}
/// Represents different material states in Dwarf Fortress.
#[derive(Debug, Clone, Copy)]
pub enum MaterialState {
/// Solid state (e.g., ice, stone)
Solid,
/// Liquid state (e.g., water, magma)
Liquid,
/// Gas state (e.g., steam, miasma)
Gas,
}/// Provides search functionality for game objects.
///
/// Implement this trait for types that should be searchable by
/// generating search strings from their properties.
///
/// # Examples
///
/// ```
/// use dfraw_parser::traits::Searchable;
///
/// struct MyObject {
/// name: String,
/// description: String,
/// }
///
/// impl Searchable for MyObject {
/// fn get_search_vec(&self) -> Vec<String> {
/// vec![self.name.clone(), self.description.clone()]
/// }
/// }
/// ```
pub trait Searchable {
/// Returns a vector of searchable strings for this object.
fn get_search_vec(&self) -> Vec<String>;
}See the documentation reference for more examples of how to document this library.
Use these attributes as appropriate:
no_run- Code compiles but shouldn't be executed (e.g., needs external files)ignore- Skip this example in testsshould_panic- Example is expected to paniccompile_fail- Example should fail to compile (for demonstrating errors)
/// # Examples
///
/// ```no_run
/// use dfraw_parser::parse;
///
/// // This needs actual game files to run
/// let result = parse(&options);
/// ```
Run doc tests to ensure examples work:
cargo test --docGenerate and view documentation locally:
cargo doc --no-deps --open- Follow the Rust API Guidelines
- Use
rustfmtfor code formatting:cargo fmt - Use
clippyfor linting:cargo clippy - Avoid
unwrap()in library code (use proper error handling)
This project enforces strict lints:
[workspace.lints.rust]
unsafe_code = "forbid"
missing_docs = "warn"
unreachable_code = "warn"
unreachable_patterns = "warn"
[workspace.lints.clippy]
enum_glob_use = "deny"
pedantic = "deny"
nursery = "deny"
unwrap_used = "deny"- Use
snake_casefor functions, methods, variables, and modules - Use
CamelCasefor types (structs, enums, traits) - Use
SCREAMING_SNAKE_CASEfor constants - Use descriptive names that indicate purpose
- Use
Result<T, E>for operations that can fail - Define specific error types using
thiserror - Provide context in error messages
- Document error conditions in function docs
/// # Errors
///
/// Returns `ParserError::InvalidToken` if the token format is invalid.
/// Returns `ParserError::IoError` if file reading fails.
pub fn parse_file(path: &Path) -> Result<ParsedFile, ParserError> {
// implementation
}- Unit tests go in a
testsmodule within the same file - Integration tests go in the
tests/directory - Use descriptive test names that indicate what is being tested
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_valid_creature_tag() {
let result = parse_creature_tag("[CREATURE:DOG]");
assert!(result.is_ok());
assert_eq!(result.unwrap().identifier, "DOG");
}
#[test]
fn test_parse_invalid_creature_tag_returns_error() {
let result = parse_creature_tag("[INVALID]");
assert!(result.is_err());
}
}- Aim for high test coverage of public APIs
- Test both success and error cases
- Test edge cases and boundary conditions
- Use property-based testing for complex logic (consider
proptest)
- Ensure tests pass:
cargo test --workspace - Run clippy:
cargo clippy --workspace -- -D warnings - Format code:
cargo fmt --all - Update documentation: Ensure all public APIs are documented
- Add/update tests: Include tests for new functionality
- Update CHANGELOG.md: Add an entry describing your changes
## Description
Brief description of what this PR does.
## Motivation
Why is this change needed? What problem does it solve?
## Changes
- List of specific changes made
- Use bullet points
## Testing
How was this tested? What test cases were added?
## Documentation
- [ ] Added/updated documentation comments
- [ ] Updated README if needed
- [ ] Added examples if appropriate
## Checklist
- [ ] Tests pass locally
- [ ] Code is formatted (`cargo fmt`)
- [ ] No clippy warnings (`cargo clippy`)
- [ ] Documentation is complete
- [ ] CHANGELOG.md is updated- Maintainers will review your PR
- Address any requested changes
- Once approved, your PR will be merged
- Celebrate your contribution! 🎉
If you have questions or need help:
- Open an issue with the question
- Check existing issues and discussions
- Review the README and documentation
Thank you for contributing to dfraw_parser!