Thank you for your interest in contributing to tinyxml2-rs! Every contribution matters — whether it's a bug report, a feature suggestion, a documentation improvement, or a code change.
- Code of Conduct
- How to Contribute
- Development Setup
- Code Style
- Testing
- Pull Request Process
- Commit Convention
- Architecture Reference
- Getting Help
This project follows the Contributor Covenant Code of Conduct. By participating, you agree to uphold a welcoming, inclusive, and harassment-free environment for everyone.
Found a bug? We appreciate you taking the time to report it.
- Search existing issues to check if it's already been reported.
- Open a new issue using the bug report template.
- Include the following information:
- A clear, descriptive title
- Steps to reproduce the issue
- Expected behavior vs. actual behavior
- The XML input that triggers the problem (if applicable)
- Your Rust version (
rustc --version) and OS - Any relevant error messages or stack traces
Security vulnerabilities should be reported privately. See SECURITY.md.
Have an idea for an improvement?
- Check the ROADMAP.md to see if it's already planned.
- Search existing issues for similar suggestions.
- Open a new issue using the feature request template.
- Describe:
- The problem your feature would solve
- Your proposed solution or API sketch
- Any alternatives you've considered
- How it relates to TinyXML2 behavioral compatibility
Ready to write code? Great! Here's the workflow:
- Fork the repository.
- Create a feature branch from
main(git checkout -b feat/my-feature). - Make your changes following the guidelines below.
- Commit using conventional commits.
- Push to your fork and open a pull request.
- Rust (stable toolchain — managed via
rust-toolchain.toml) - Git
# Clone your fork
git clone https://github.com/<your-username>/tinyxml2-rs.git
cd tinyxml2-rs
# Build the entire workspace
cargo build
# Run all tests
cargo test --workspace
# Run clippy lints
cargo clippy --workspace --all-targets -- -D warnings
# Check formatting
cargo fmt --all -- --check| Command | Description |
|---|---|
cargo build |
Build all crates |
cargo test --workspace |
Run all tests across the workspace |
cargo clippy --workspace --all-targets -- -D warnings |
Run lint checks |
cargo fmt --all |
Format all code |
cargo fmt --all -- --check |
Check formatting without modifying files |
cargo doc --workspace --no-deps --open |
Build and open documentation |
cargo bench -p tinyxml2-bench |
Run benchmarks |
We enforce consistent code style across the project:
- All code must be formatted with
rustfmtusing the project's rustfmt.toml. - Run
cargo fmt --allbefore committing. - CI will reject PRs with formatting issues.
- All code must pass
clippywith zero warnings. - Run
cargo clippy --workspace --all-targets -- -D warnings. - If you believe a clippy lint is a false positive, discuss it in your PR before adding an
#[allow(...)].
- Prefer safe Rust. The core
tinyxml2crate must contain nounsafecode. Thetinyxml2-capicrate may useunsafewhere required for FFI boundaries. - Write idiomatic Rust. Leverage the type system, use
Resultfor fallible operations, and prefer iterators over manual loops. - Document public APIs. Every public type, function, and method must have a doc comment (
///). - Keep functions focused. Each function should do one thing well.
- Use meaningful names. Variable and function names should be descriptive and self-documenting.
- Preserve existing comments. Don't remove or alter comments unrelated to your change.
Testing is critical for a library that targets behavioral compatibility. We maintain several layers of tests:
| Category | Location | Purpose |
|---|---|---|
| Unit tests | #[cfg(test)] modules in source files |
Test individual functions and types |
| Integration tests | tests/ |
Test cross-module behavior |
| Conformance tests | spec/ |
Verify behavioral parity with TinyXML2 |
| Fuzz tests | fuzz/ |
Find crashes and edge cases via random input |
- All new code must have tests. Aim for comprehensive coverage of both success and failure paths.
- All existing tests must pass. Run
cargo test --workspaceand ensure zero failures. - Bug fixes must include a regression test. Add a test that fails without your fix and passes with it.
- Conformance tests are particularly important. If your change affects parsing or output behavior, add or update conformance tests in
spec/.
# Run all tests
cargo test --workspace
# Run tests for a specific crate
cargo test -p tinyxml2
# Run a specific test by name
cargo test --workspace -- test_name
# Run tests with output
cargo test --workspace -- --nocapture-
Ensure all checks pass locally before opening a PR:
cargo build --workspacecargo test --workspacecargo clippy --workspace --all-targets -- -D warningscargo fmt --all -- --check
-
Fill out the PR template completely:
- Describe what the PR does and why
- Reference any related issues (
Fixes #123,Closes #456) - Note any breaking changes
-
Keep PRs focused. One logical change per PR. If you find unrelated issues, open separate PRs.
-
Respond to review feedback promptly. Discussions are how we improve the code together.
-
Squash commits if requested. We prefer a clean commit history on
main.
- Code compiles without warnings
- All tests pass (
cargo test --workspace) - Clippy passes with no warnings
- Code is formatted with
rustfmt - Public APIs have doc comments
- New functionality has tests
- Relevant documentation is updated
- Commit messages follow conventional commit format
We follow the Conventional Commits specification:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
| Type | When to Use |
|---|---|
feat |
A new feature |
fix |
A bug fix |
docs |
Documentation changes only |
style |
Formatting, whitespace — no code logic changes |
refactor |
Code change that neither fixes a bug nor adds a feature |
perf |
A code change that improves performance |
test |
Adding or updating tests |
build |
Changes to the build system or dependencies |
ci |
Changes to CI configuration |
chore |
Other changes that don't modify src or test files |
Use the crate name as the scope: core, capi, bench, or workspace for cross-cutting changes.
feat(core): implement arena-based node allocation
fix(core): handle self-closing tags with whitespace
docs: update README with quick start example
test(core): add conformance tests for entity decoding
refactor(capi): simplify FFI error conversion
Before contributing, familiarize yourself with the project's architecture:
- ARCHITECTURE.md — Detailed overview of the crate structure, module layout, and design decisions.
- ROADMAP.md — Current development phase and planned milestones.
- Generational Arena: The DOM uses a generational arena for node storage. Nodes are referenced by
NodeIdhandles rather than pointers. - Behavioral Compatibility: We treat TinyXML2 as a specification. When in doubt about behavior, match what TinyXML2 does.
- Recursive Descent Parser: The parser is hand-written, not generated. It mirrors TinyXML2's parsing strategy.
- Safe FFI Boundary: The
tinyxml2-capicrate contains theunsafeboundary. Everything else stays safe.
- Questions? Open a Discussion on GitHub.
- Stuck on a contribution? Mention it in your PR or issue — we're happy to help.
- Security concerns? See SECURITY.md.
Thank you for helping make tinyxml2-rs better! 🦀