# Contributing to rok-utils
Thank you for your interest in contributing to rok-utils!
## Getting Started
1. Fork the repository
2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/rok-utils.git`
3. Add upstream: `git remote add upstream https://github.com/ateeq1999/rok-utils.git`
4. Install Rust (latest stable)
5. Run tests: `cargo test --all-features`
## Development Workflow
### 1. Create a Branch
```bash
git checkout -b feature/your-feature-name
```
### 2. Make Changes
Follow the coding standards:
- Run `cargo fmt` before committing
- Run `cargo clippy --all-features -- -D warnings` to catch issues
- Add tests for new functionality
- Keep files under 400 lines
### 3. Test Your Changes
```bash
# Run all tests
cargo test --all-features
# Run doc tests
cargo test --doc
# Check formatting
cargo fmt --check
# Run clippy
cargo clippy --all-features -- -D warnings
```
### 4. Commit and Push
```bash
git add .
git commit -m "feat: add new feature"
git push origin feature/your-feature-name
```
### 5. Open a Pull Request
Open a PR against `main` with a clear description of your changes.
## Coding Standards
### Error Handling
- Never use `unwrap()` in library code
- Return `Result<T, RokError>` or `Option<T>` for fallible operations
- Use the `context()` method for adding error context
```rust
// Good
fn read_config(path: &str) -> Result<Config, RokError> {
std::fs::read_to_string(path)
.context("Failed to read config file")
.and_then(|content| {
serde_json::from_str(&content)
.context("Failed to parse config")
})
}
// Avoid
fn read_config(path: &str) -> Config {
std::fs::read_to_string(path).unwrap() // Never do this!
}
```
### String Operations
- Use `chars()` for character iteration (UTF-8 native)
- Never assume ASCII-only input
### Naming Conventions
- Functions: `snake_case` (e.g., `to_snake_case`)
- Types: `PascalCase` (e.g., `RokError`, `Str`)
- Traits: `PascalCase` (e.g., `ResultExt`)
- Constants: `SCREAMING_SNAKE_CASE`
### Module Organization
- Each module should be under 400 lines
- Use feature flags for heavy dependencies
- Export only public API from `lib.rs`
## Adding New Functions
### 1. Function Template
```rust
/// Brief description of what the function does.
///
/// Longer description if needed, explaining behavior
/// and edge cases.
///
/// # Arguments
///
/// * `input` - Description of input parameter
///
/// # Examples
///
/// ```rust
/// use rok_utils::module_name::new_function;
/// assert_eq!(new_function("test"), "expected");
/// ```
///
/// # See Also
///
/// * [`related_function`] for similar functionality
pub fn new_function(input: &str) -> String {
// Implementation
}
```
### 2. Add Tests
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_function_basic() {
assert_eq!(new_function("test"), "expected");
}
#[test]
fn test_new_function_empty() {
assert_eq!(new_function(""), "");
}
}
```
### 3. Feature Flag (if needed)
```rust
#[cfg(feature = "your-feature")]
pub fn new_function(input: &str) -> String {
// Implementation
}
```
## Adding New Modules
1. Create the module file: `src/module_name.rs`
2. Add module declaration: `pub mod module_name;` in `lib.rs`
3. Add re-exports: `pub use module_name::*;`
4. Add tests inline with `#[cfg(test)] mod tests`
5. Update documentation
## Documentation
### Inline Documentation
- Document all public items
- Include examples for public functions
- Use proper Markdown formatting
### Module README
- Update `src/module_name/README.md` with overview
- Include quick start examples
- Document feature flags
## Reporting Issues
- Use GitHub Issues for bugs and feature requests
- Include minimal reproduction steps
- Specify Rust version and feature flags used
## Code of Conduct
- Be respectful and inclusive
- Focus on constructive feedback
- Follow Rust's community guidelines
## License
By contributing, you agree that your contributions will be licensed under the MIT License.