Documentation
Documentation is a first-class citizen in Rust. The rustdoc
tool makes it easy to generate beautiful, searchable HTML documentation directly from your code and comments.
Rustdoc Basics
Getting Started with Rustdoc
//! This is a crate-level documentation comment.
//!
//! This crate provides utilities for mathematical operations
//! including basic arithmetic and advanced functions.
//!
//! # Examples
//!
//! ```
//! use my_math_crate::Calculator;
//!
//! let calc = Calculator::new();
//! assert_eq!(calc.add(2, 3), 5);
//! ```
/// Represents a calculator that can perform basic mathematical operations.
///
/// The Calculator struct provides methods for addition, subtraction,
/// multiplication, and division operations.
///
/// # Examples
///
/// ```
/// use my_math_crate::Calculator;
///
/// let calc = Calculator::new();
/// assert_eq!(calc.add(10, 5), 15);
/// assert_eq!(calc.subtract(10, 5), 5);
/// ```
pub struct Calculator {
/// The current value stored in the calculator
pub value: f64,
}
impl Calculator {
/// Creates a new Calculator with an initial value of 0.0.
///
/// # Examples
///
/// ```
/// use my_math_crate::Calculator;
///
/// let calc = Calculator::new();
/// assert_eq!(calc.value, 0.0);
/// ```
pub fn new() -> Self {
Calculator { value: 0.0 }
}
/// Adds two numbers and returns the result.
///
/// # Arguments
///
/// * `a` - The first number to add
/// * `b` - The second number to add
///
/// # Examples
///
/// ```
/// use my_math_crate::Calculator;
///
/// let calc = Calculator::new();
/// assert_eq!(calc.add(2, 3), 5);
/// assert_eq!(calc.add(-1, 1), 0);
/// ```
pub fn add(&self, a: f64, b: f64) -> f64 {
a + b
}
/// Divides two numbers and returns the result.
///
/// # Arguments
///
/// * `a` - The dividend
/// * `b` - The divisor
///
/// # Returns
///
/// Returns `Ok(result)` if the operation is successful, or `Err(error_message)`
/// if division by zero is attempted.
///
/// # Errors
///
/// This function will return an error if `b` is zero.
///
/// # Examples
///
/// ```
/// use my_math_crate::Calculator;
///
/// let calc = Calculator::new();
/// assert_eq!(calc.divide(10.0, 2.0), Ok(5.0));
/// assert!(calc.divide(10.0, 0.0).is_err());
/// ```
pub fn divide(&self, a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
}
Generating Documentation
# Generate documentation for your crate
cargo doc
# Generate and open documentation in browser
cargo doc --open
# Include private items in documentation
cargo doc --document-private-items
# Generate documentation for dependencies
cargo doc --include-deps
# Generate documentation without running examples
cargo doc --no-deps
Documentation Comments
Types of Documentation Comments
//! Crate-level documentation
//! This appears at the top of the crate documentation
/// Item-level documentation
/// This documents the following item (function, struct, etc.)
pub struct Example;
impl Example {
/// Method documentation
///
/// This documents the following method
pub fn method(&self) {}
}
/// Module documentation
///
/// This module contains utility functions
pub mod utils {
//! Inner module documentation
//! This appears at the top of the module documentation
/// Function documentation
pub fn helper() {}
}
Documentation Attributes
#![doc = "Crate-level documentation using attributes"]
#[doc = "Struct documentation using attributes"]
pub struct AttributeExample;
#[doc(hidden)]
pub fn internal_function() {
// This function won't appear in generated documentation
}
#[doc(alias = "calculate")]
#[doc(alias = "compute")]
/// Performs a computation
///
/// This function can be found by searching for "calculate" or "compute"
pub fn perform_computation() {}
/// A function with multiple aliases
#[doc(alias = "add")]
#[doc(alias = "sum")]
#[doc(alias = "plus")]
pub fn addition(a: i32, b: i32) -> i32 {
a + b
}
Code Examples in Documentation
Basic Examples
/// Calculates the factorial of a number.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use my_crate::factorial;
///
/// assert_eq!(factorial(5), 120);
/// assert_eq!(factorial(0), 1);
/// ```
///
/// The function handles edge cases:
///
/// ```
/// use my_crate::factorial;
///
/// // Zero factorial is 1
/// assert_eq!(factorial(0), 1);
///
/// // One factorial is 1
/// assert_eq!(factorial(1), 1);
/// ```
pub fn factorial(n: u32) -> u64 {
match n {
0 | 1 => 1,
_ => n as u64 * factorial(n - 1),
}
}
Advanced Example Patterns
/// A thread-safe counter using atomic operations.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use my_crate::AtomicCounter;
///
/// let counter = AtomicCounter::new();
/// assert_eq!(counter.get(), 0);
///
/// counter.increment();
/// assert_eq!(counter.get(), 1);
/// ```
///
/// Thread-safe usage:
///
/// ```
/// use my_crate::AtomicCounter;
/// use std::sync::Arc;
/// use std::thread;
///
/// let counter = Arc::new(AtomicCounter::new());
/// let mut handles = vec![];
///
/// for _ in 0..10 {
/// let counter = Arc::clone(&counter);
/// let handle = thread::spawn(move || {
/// for _ in 0..100 {
/// counter.increment();
/// }
/// });
/// handles.push(handle);
/// }
///
/// for handle in handles {
/// handle.join().unwrap();
/// }
///
/// assert_eq!(counter.get(), 1000);
/// ```
///
/// Error handling example:
///
/// ```should_panic
/// use my_crate::AtomicCounter;
///
/// let counter = AtomicCounter::new();
/// // This will panic because we can't decrement below zero
/// counter.decrement();
/// ```
///
/// Example that should not be run (compile-only):
///
/// ```no_run
/// use my_crate::AtomicCounter;
/// use std::fs::File;
///
/// let counter = AtomicCounter::new();
///
/// // This example shows API usage but shouldn't be executed
/// // because it tries to open a file that might not exist
/// let file = File::open("config.txt").unwrap();
/// ```
///
/// Example showing compilation failure:
///
/// ```compile_fail
/// use my_crate::AtomicCounter;
///
/// let counter = AtomicCounter::new();
/// let value: String = counter.get(); // This won't compile - type mismatch
/// ```
use std::sync::atomic::{AtomicU64, Ordering};
pub struct AtomicCounter {
value: AtomicU64,
}
impl AtomicCounter {
pub fn new() -> Self {
AtomicCounter {
value: AtomicU64::new(0),
}
}
pub fn increment(&self) {
self.value.fetch_add(1, Ordering::SeqCst);
}
pub fn decrement(&self) {
let old_value = self.value.fetch_sub(1, Ordering::SeqCst);
if old_value == 0 {
panic!("Cannot decrement below zero");
}
}
pub fn get(&self) -> u64 {
self.value.load(Ordering::SeqCst)
}
}
Testing Documentation Examples
/// A simple string utility function.
///
/// # Examples
///
/// ```
/// use my_crate::reverse_string;
///
/// assert_eq!(reverse_string("hello"), "olleh");
/// assert_eq!(reverse_string(""), "");
/// ```
///
/// Example with Unicode characters:
///
/// ```
/// use my_crate::reverse_string;
///
/// assert_eq!(reverse_string("👨💻🦀"), "🦀💻👨"); // Note: This might not work as expected
/// ```
///
/// Example showing performance characteristics:
///
/// ```
/// use my_crate::reverse_string;
///
/// let long_string = "a".repeat(1000);
/// let reversed = reverse_string(&long_string);
/// assert_eq!(reversed.len(), 1000);
/// assert!(reversed.chars().all(|c| c == 'a'));
/// ```
pub fn reverse_string(s: &str) -> String {
s.chars().rev().collect()
}
// Test documentation examples
#[cfg(doctest)]
mod doctests {
/// This module contains additional tests for documentation examples
/// that need more complex setup or verification.
#[test]
fn test_reverse_string_comprehensive() {
use super::reverse_string;
// Test cases not suitable for doc examples
let test_cases = vec![
("", ""),
("a", "a"),
("ab", "ba"),
("hello world", "dlrow olleh"),
("12345", "54321"),
];
for (input, expected) in test_cases {
assert_eq!(reverse_string(input), expected);
}
}
}
Documenting Complex APIs
Documenting Enums and Traits
/// Represents different types of geometric shapes.
///
/// This enum provides a type-safe way to work with various shapes
/// and calculate their properties.
///
/// # Examples
///
/// ```
/// use my_crate::Shape;
///
/// let circle = Shape::Circle { radius: 5.0 };
/// let rectangle = Shape::Rectangle { width: 10.0, height: 5.0 };
///
/// assert_eq!(circle.area(), std::f64::consts::PI * 25.0);
/// assert_eq!(rectangle.area(), 50.0);
/// ```
#[derive(Debug, Clone, PartialEq)]
pub enum Shape {
/// A circle with a given radius.
///
/// # Examples
///
/// ```
/// use my_crate::Shape;
///
/// let circle = Shape::Circle { radius: 3.0 };
/// assert!(circle.area() > 28.0 && circle.area() < 29.0);
/// ```
Circle {
/// The radius of the circle in units
radius: f64,
},
/// A rectangle with width and height.
///
/// # Examples
///
/// ```
/// use my_crate::Shape;
///
/// let rect = Shape::Rectangle { width: 4.0, height: 6.0 };
/// assert_eq!(rect.area(), 24.0);
/// ```
Rectangle {
/// The width of the rectangle
width: f64,
/// The height of the rectangle
height: f64,
},
/// A triangle with base and height.
Triangle {
/// The base length of the triangle
base: f64,
/// The height of the triangle
height: f64,
},
}
/// Trait for calculating geometric properties.
///
/// This trait provides common methods that all geometric shapes should implement.
///
/// # Examples
///
/// Implementing for a custom shape:
///
/// ```
/// use my_crate::Geometry;
///
/// struct Square {
/// side: f64,
/// }
///
/// impl Geometry for Square {
/// fn area(&self) -> f64 {
/// self.side * self.side
/// }
///
/// fn perimeter(&self) -> f64 {
/// 4.0 * self.side
/// }
/// }
///
/// let square = Square { side: 5.0 };
/// assert_eq!(square.area(), 25.0);
/// assert_eq!(square.perimeter(), 20.0);
/// ```
pub trait Geometry {
/// Calculates the area of the shape.
///
/// # Returns
///
/// The area in square units.
///
/// # Examples
///
/// ```
/// use my_crate::{Shape, Geometry};
///
/// let circle = Shape::Circle { radius: 2.0 };
/// let area = circle.area();
/// assert!(area > 12.0 && area < 13.0);
/// ```
fn area(&self) -> f64;
/// Calculates the perimeter of the shape.
///
/// # Returns
///
/// The perimeter in linear units.
fn perimeter(&self) -> f64;
/// Checks if the shape is valid (all dimensions are positive).
///
/// # Returns
///
/// `true` if the shape has valid dimensions, `false` otherwise.
///
/// # Examples
///
/// ```
/// use my_crate::{Shape, Geometry};
///
/// let valid_circle = Shape::Circle { radius: 5.0 };
/// let invalid_circle = Shape::Circle { radius: -1.0 };
///
/// assert!(valid_circle.is_valid());
/// assert!(!invalid_circle.is_valid());
/// ```
fn is_valid(&self) -> bool {
self.area() >= 0.0 && self.perimeter() >= 0.0
}
}
impl Geometry for Shape {
fn area(&self) -> f64 {
match self {
Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
Shape::Rectangle { width, height } => width * height,
Shape::Triangle { base, height } => 0.5 * base * height,
}
}
fn perimeter(&self) -> f64 {
match self {
Shape::Circle { radius } => 2.0 * std::f64::consts::PI * radius,
Shape::Rectangle { width, height } => 2.0 * (width + height),
Shape::Triangle { base, height } => {
// Assuming isosceles triangle for simplicity
let side = (height * height + (base / 2.0) * (base / 2.0)).sqrt();
base + 2.0 * side
}
}
}
}
Documenting Error Types
/// Errors that can occur during mathematical operations.
///
/// This enum represents all possible errors that mathematical functions
/// in this crate can return.
///
/// # Examples
///
/// ```
/// use my_crate::{MathError, divide};
///
/// match divide(10.0, 0.0) {
/// Ok(result) => println!("Result: {}", result),
/// Err(MathError::DivisionByZero) => println!("Cannot divide by zero!"),
/// Err(err) => println!("Math error: {}", err),
/// }
/// ```
#[derive(Debug, Clone, PartialEq)]
pub enum MathError {
/// Attempted to divide by zero.
///
/// This error occurs when trying to divide any number by zero,
/// which is mathematically undefined.
///
/// # Examples
///
/// ```
/// use my_crate::{MathError, divide};
///
/// assert_eq!(divide(5.0, 0.0), Err(MathError::DivisionByZero));
/// ```
DivisionByZero,
/// Input value is out of the valid range.
///
/// This error occurs when an input value is outside the acceptable
/// range for a mathematical operation.
///
/// # Examples
///
/// ```
/// use my_crate::{MathError, square_root};
///
/// assert_eq!(square_root(-1.0), Err(MathError::InvalidInput {
/// value: -1.0,
/// expected: "non-negative number".to_string(),
/// }));
/// ```
InvalidInput {
/// The invalid input value
value: f64,
/// Description of what was expected
expected: String,
},
/// Numeric overflow occurred during calculation.
///
/// This error occurs when a calculation result is too large
/// to be represented by the numeric type.
Overflow,
/// Numeric underflow occurred during calculation.
///
/// This error occurs when a calculation result is too small
/// to be represented by the numeric type.
Underflow,
}
impl std::fmt::Display for MathError {
/// Formats the error for display.
///
/// # Examples
///
/// ```
/// use my_crate::MathError;
///
/// let error = MathError::DivisionByZero;
/// assert_eq!(format!("{}", error), "Division by zero");
/// ```
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MathError::DivisionByZero => write!(f, "Division by zero"),
MathError::InvalidInput { value, expected } => {
write!(f, "Invalid input {}: expected {}", value, expected)
}
MathError::Overflow => write!(f, "Numeric overflow"),
MathError::Underflow => write!(f, "Numeric underflow"),
}
}
}
impl std::error::Error for MathError {}
/// Divides two numbers safely.
///
/// # Arguments
///
/// * `a` - The dividend
/// * `b` - The divisor
///
/// # Returns
///
/// Returns `Ok(result)` if successful, or `Err(MathError)` if an error occurs.
///
/// # Errors
///
/// This function will return:
/// - `MathError::DivisionByZero` if `b` is zero
/// - `MathError::Overflow` if the result is too large
/// - `MathError::InvalidInput` if inputs are NaN or infinite
///
/// # Examples
///
/// ```
/// use my_crate::{divide, MathError};
///
/// assert_eq!(divide(10.0, 2.0), Ok(5.0));
/// assert_eq!(divide(10.0, 0.0), Err(MathError::DivisionByZero));
/// ```
pub fn divide(a: f64, b: f64) -> Result<f64, MathError> {
if b == 0.0 {
return Err(MathError::DivisionByZero);
}
if a.is_nan() || a.is_infinite() || b.is_nan() || b.is_infinite() {
return Err(MathError::InvalidInput {
value: if a.is_nan() || a.is_infinite() { a } else { b },
expected: "finite number".to_string(),
});
}
let result = a / b;
if result.is_infinite() {
Err(MathError::Overflow)
} else {
Ok(result)
}
}
Module and Crate Documentation
Crate-Level Documentation
//! # My Math Crate
//!
//! `my_math_crate` is a comprehensive mathematics library providing
//! safe and efficient mathematical operations.
//!
//! ## Features
//!
//! - Basic arithmetic operations with overflow protection
//! - Advanced mathematical functions (trigonometry, logarithms)
//! - Geometric shape calculations
//! - Statistical functions
//! - Complex number support
//!
//! ## Quick Start
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! my_math_crate = "1.0"
//! ```
//!
//! Then use it in your code:
//!
//! ```
//! use my_math_crate::{Calculator, Shape, Geometry};
//!
//! // Basic arithmetic
//! let calc = Calculator::new();
//! let result = calc.add(2.0, 3.0);
//!
//! // Geometry calculations
//! let circle = Shape::Circle { radius: 5.0 };
//! let area = circle.area();
//! ```
//!
//! ## Modules
//!
//! - [`arithmetic`] - Basic arithmetic operations
//! - [`geometry`] - Geometric shape calculations
//! - [`statistics`] - Statistical functions
//! - [`complex`] - Complex number operations
//!
//! ## Error Handling
//!
//! All functions that can fail return a `Result` type. Common errors
//! include division by zero, numeric overflow, and invalid inputs.
//!
//! ```
//! use my_math_crate::{divide, MathError};
//!
//! match divide(10.0, 0.0) {
//! Ok(result) => println!("Result: {}", result),
//! Err(MathError::DivisionByZero) => println!("Cannot divide by zero!"),
//! Err(err) => println!("Error: {}", err),
//! }
//! ```
/// Basic arithmetic operations with error handling.
///
/// This module provides safe arithmetic functions that handle
/// edge cases like overflow, underflow, and division by zero.
///
/// # Examples
///
/// ```
/// use my_math_crate::arithmetic::{add, subtract, multiply, divide};
///
/// assert_eq!(add(2.0, 3.0), Ok(5.0));
/// assert_eq!(subtract(10.0, 3.0), Ok(7.0));
/// assert_eq!(multiply(4.0, 5.0), Ok(20.0));
/// assert_eq!(divide(10.0, 2.0), Ok(5.0));
/// ```
pub mod arithmetic {
use crate::MathError;
/// Adds two numbers safely.
pub fn add(a: f64, b: f64) -> Result<f64, MathError> {
let result = a + b;
if result.is_infinite() {
Err(MathError::Overflow)
} else {
Ok(result)
}
}
// Other arithmetic functions...
}
/// Geometric shape calculations and utilities.
///
/// This module provides types and functions for working with
/// geometric shapes and calculating their properties.
///
/// # Supported Shapes
///
/// - Circles
/// - Rectangles
/// - Triangles
/// - Polygons (coming soon)
///
/// # Examples
///
/// ```
/// use my_math_crate::geometry::{Shape, Geometry};
///
/// let shapes = vec![
/// Shape::Circle { radius: 5.0 },
/// Shape::Rectangle { width: 10.0, height: 5.0 },
/// ];
///
/// for shape in shapes {
/// println!("Area: {}", shape.area());
/// println!("Perimeter: {}", shape.perimeter());
/// }
/// ```
pub mod geometry {
//! Geometric calculations and shape definitions.
//!
//! This module contains everything needed for geometric calculations,
//! including shape definitions, area calculations, and geometric utilities.
pub use crate::{Shape, Geometry};
/// Utility functions for geometric calculations.
pub mod utils {
/// Converts degrees to radians.
///
/// # Examples
///
/// ```
/// use my_math_crate::geometry::utils::degrees_to_radians;
///
/// let radians = degrees_to_radians(180.0);
/// assert!((radians - std::f64::consts::PI).abs() < 1e-10);
/// ```
pub fn degrees_to_radians(degrees: f64) -> f64 {
degrees * std::f64::consts::PI / 180.0
}
}
}
Module Organization
//! # Web Server Module
//!
//! This module provides a complete web server implementation with
//! routing, middleware support, and request/response handling.
/// HTTP server implementation.
///
/// This module contains the core server functionality including
/// request routing, middleware processing, and response generation.
///
/// # Examples
///
/// ```no_run
/// use my_web_crate::server::Server;
///
/// let server = Server::new("127.0.0.1:8080");
/// server.run().await.unwrap();
/// ```
pub mod server {
//! Core server functionality.
//!
//! Contains the main server struct and related functionality
//! for handling HTTP requests and responses.
/// The main server struct.
pub struct Server {
address: String,
}
impl Server {
/// Creates a new server instance.
pub fn new(address: &str) -> Self {
Server {
address: address.to_string(),
}
}
/// Starts the server.
pub async fn run(&self) -> Result<(), Box<dyn std::error::Error>> {
// Server implementation
Ok(())
}
}
}
/// Request routing functionality.
///
/// This module provides types and functions for defining routes
/// and handling HTTP requests.
///
/// # Route Definition
///
/// ```
/// use my_web_crate::routing::{Router, Route, Method};
///
/// let mut router = Router::new();
/// router.add_route(Route::new(Method::GET, "/users", handle_users));
/// router.add_route(Route::new(Method::POST, "/users", create_user));
/// ```
pub mod routing {
/// HTTP methods supported by the router.
#[derive(Debug, Clone, PartialEq)]
pub enum Method {
GET,
POST,
PUT,
DELETE,
}
/// Represents a single route in the application.
pub struct Route {
method: Method,
path: String,
}
/// The main router for handling requests.
pub struct Router {
routes: Vec<Route>,
}
impl Router {
/// Creates a new empty router.
pub fn new() -> Self {
Router {
routes: Vec::new(),
}
}
}
}
/// Middleware support for request/response processing.
///
/// Middleware functions can be used to add cross-cutting concerns
/// like authentication, logging, and request validation.
///
/// # Creating Middleware
///
/// ```
/// use my_web_crate::middleware::{Middleware, Request, Response};
///
/// struct LoggingMiddleware;
///
/// impl Middleware for LoggingMiddleware {
/// fn process(&self, req: &Request) -> Result<Option<Response>, String> {
/// println!("Processing request: {} {}", req.method(), req.path());
/// Ok(None) // Continue to next middleware
/// }
/// }
/// ```
pub mod middleware {
/// Trait for implementing middleware.
pub trait Middleware {
/// Process a request and optionally return a response.
fn process(&self, req: &Request) -> Result<Option<Response>, String>;
}
/// HTTP request representation.
pub struct Request {
method: String,
path: String,
}
impl Request {
/// Gets the HTTP method.
pub fn method(&self) -> &str {
&self.method
}
/// Gets the request path.
pub fn path(&self) -> &str {
&self.path
}
}
/// HTTP response representation.
pub struct Response {
status: u16,
body: String,
}
}
Testing Documentation
Doctests
# Run documentation tests
cargo test --doc
# Run doctests for a specific crate
cargo test --doc --package my_crate
# Show output from doctests
cargo test --doc -- --nocapture
# Run doctests with specific features enabled
cargo test --doc --features "feature1,feature2"
Advanced Doctest Configuration
/// A function that demonstrates various doctest features.
///
/// # Basic Example
///
/// ```
/// use my_crate::advanced_function;
///
/// let result = advanced_function(42);
/// assert_eq!(result, 84);
/// ```
///
/// # Example with setup
///
/// ```
/// # use my_crate::advanced_function;
/// # fn setup() -> i32 { 42 }
/// let input = setup(); // This line is hidden from documentation
/// let result = advanced_function(input);
/// assert_eq!(result, 84);
/// ```
///
/// # Example that should panic
///
/// ```should_panic
/// use my_crate::advanced_function;
///
/// // This will panic with negative input
/// advanced_function(-1);
/// ```
///
/// # Example with custom panic message
///
/// ```should_panic = "Input must be non-negative"
/// use my_crate::advanced_function;
///
/// advanced_function(-5);
/// ```
///
/// # Example that shouldn't run (compile only)
///
/// ```no_run
/// use my_crate::advanced_function;
/// use std::process;
///
/// let result = advanced_function(100);
/// if result > 1000 {
/// process::exit(1); // We don't want to actually exit during tests
/// }
/// ```
///
/// # Example showing compilation error
///
/// ```compile_fail
/// use my_crate::advanced_function;
///
/// // This won't compile - wrong argument type
/// let result = advanced_function("not a number");
/// ```
///
/// # Example with ignore
///
/// ```ignore
/// use my_crate::advanced_function;
///
/// // This example is ignored - maybe it requires special setup
/// // or external dependencies not available in test environment
/// let result = advanced_function(load_from_database());
/// ```
///
/// # Example with edition specification
///
/// ```edition2018
/// use my_crate::advanced_function;
///
/// async fn example() {
/// let result = advanced_function(42);
/// println!("Result: {}", result);
/// }
/// ```
pub fn advanced_function(input: i32) -> i32 {
if input < 0 {
panic!("Input must be non-negative");
}
input * 2
}
#[cfg(test)]
mod tests {
use super::*;
/// Test helper for doctests that need complex setup.
///
/// This function can be used in doctests that are marked with `# `
/// to hide the setup code from the documentation.
#[doc(hidden)]
pub fn setup_test_environment() -> TestEnvironment {
TestEnvironment::new()
}
pub struct TestEnvironment {
// Test environment state
}
impl TestEnvironment {
pub fn new() -> Self {
TestEnvironment {}
}
}
}
Documentation Best Practices
Writing Effective Documentation
/// A well-documented user management system.
///
/// The `UserManager` provides a comprehensive interface for managing
/// user accounts, including creation, authentication, and profile management.
///
/// # Thread Safety
///
/// This type is thread-safe and can be shared between threads using `Arc`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use my_crate::UserManager;
///
/// let mut manager = UserManager::new();
///
/// // Create a new user
/// let user_id = manager.create_user("[email protected]", "Alice Smith").unwrap();
///
/// // Authenticate the user
/// assert!(manager.authenticate(user_id, "password123").is_ok());
///
/// // Update user profile
/// manager.update_profile(user_id, "Alice Johnson").unwrap();
/// ```
///
/// # Error Handling
///
/// All operations return `Result` types to handle potential errors:
///
/// ```
/// use my_crate::{UserManager, UserError};
///
/// let mut manager = UserManager::new();
///
/// match manager.create_user("invalid-email", "John Doe") {
/// Ok(user_id) => println!("User created with ID: {}", user_id),
/// Err(UserError::InvalidEmail) => println!("Email format is invalid"),
/// Err(err) => println!("Other error: {}", err),
/// }
/// ```
///
/// # Performance Considerations
///
/// - User lookups are O(1) average case using internal hash maps
/// - Bulk operations are more efficient than individual calls
/// - Consider using `create_users_batch` for creating multiple users
///
/// # Security Notes
///
/// - Passwords are automatically hashed using bcrypt
/// - Session tokens expire after 24 hours by default
/// - All user input is validated before processing
pub struct UserManager {
users: std::collections::HashMap<UserId, User>,
email_index: std::collections::HashMap<String, UserId>,
next_id: UserId,
}
/// Unique identifier for users in the system.
///
/// User IDs are guaranteed to be unique within a `UserManager` instance
/// and are automatically generated when creating users.
///
/// # Examples
///
/// ```
/// use my_crate::{UserManager, UserId};
///
/// let mut manager = UserManager::new();
/// let user_id: UserId = manager.create_user("[email protected]", "User Name").unwrap();
///
/// // Use the ID to retrieve user information
/// let user = manager.get_user(user_id).unwrap();
/// ```
pub type UserId = u64;
/// Represents a user in the system.
///
/// This struct contains all user information including profile data,
/// authentication details, and account metadata.
///
/// # Privacy
///
/// The password hash is not exposed through public methods to maintain security.
/// Use the `UserManager::authenticate` method to verify passwords.
#[derive(Debug, Clone)]
pub struct User {
/// The user's unique identifier
pub id: UserId,
/// The user's email address (used for login)
pub email: String,
/// The user's display name
pub name: String,
/// When the user account was created
pub created_at: chrono::DateTime<chrono::Utc>,
/// When the user last logged in
pub last_login: Option<chrono::DateTime<chrono::Utc>>,
/// Whether the user account is active
pub is_active: bool,
// Private field - not documented as it's internal
password_hash: String,
}
impl UserManager {
/// Creates a new empty user manager.
///
/// # Examples
///
/// ```
/// use my_crate::UserManager;
///
/// let manager = UserManager::new();
/// assert_eq!(manager.user_count(), 0);
/// ```
pub fn new() -> Self {
UserManager {
users: std::collections::HashMap::new(),
email_index: std::collections::HashMap::new(),
next_id: 1,
}
}
/// Creates a new user with the given email and name.
///
/// # Arguments
///
/// * `email` - A valid email address for the user
/// * `name` - The user's display name
///
/// # Returns
///
/// Returns the newly created user's ID on success.
///
/// # Errors
///
/// This function will return an error if:
/// * The email format is invalid
/// * A user with the same email already exists
/// * The name is empty or contains only whitespace
///
/// # Examples
///
/// ```
/// use my_crate::UserManager;
///
/// let mut manager = UserManager::new();
///
/// // Create a valid user
/// let user_id = manager.create_user("[email protected]", "Alice Smith").unwrap();
/// assert!(user_id > 0);
///
/// // Attempting to create a duplicate user fails
/// assert!(manager.create_user("[email protected]", "Another Alice").is_err());
/// ```
///
/// # Security
///
/// The user is created with a default password that must be changed
/// before the account can be used for authentication.
pub fn create_user(&mut self, email: &str, name: &str) -> Result<UserId, UserError> {
// Validate email format
if !self.is_valid_email(email) {
return Err(UserError::InvalidEmail);
}
// Check for duplicate email
if self.email_index.contains_key(email) {
return Err(UserError::DuplicateEmail);
}
// Validate name
let name = name.trim();
if name.is_empty() {
return Err(UserError::InvalidName);
}
let user_id = self.next_id;
self.next_id += 1;
let user = User {
id: user_id,
email: email.to_string(),
name: name.to_string(),
created_at: chrono::Utc::now(),
last_login: None,
is_active: true,
password_hash: "".to_string(), // Default empty - must be set
};
self.users.insert(user_id, user);
self.email_index.insert(email.to_string(), user_id);
Ok(user_id)
}
/// Returns the total number of users in the system.
///
/// # Examples
///
/// ```
/// use my_crate::UserManager;
///
/// let mut manager = UserManager::new();
/// assert_eq!(manager.user_count(), 0);
///
/// manager.create_user("[email protected]", "User One").unwrap();
/// manager.create_user("[email protected]", "User Two").unwrap();
/// assert_eq!(manager.user_count(), 2);
/// ```
pub fn user_count(&self) -> usize {
self.users.len()
}
// Internal helper method - not part of public API
fn is_valid_email(&self, email: &str) -> bool {
email.contains('@') && email.contains('.')
}
}
/// Errors that can occur during user management operations.
///
/// This enum represents all possible errors that can be returned
/// by `UserManager` methods.
#[derive(Debug, Clone, PartialEq)]
pub enum UserError {
/// The provided email address format is invalid.
InvalidEmail,
/// A user with the same email address already exists.
DuplicateEmail,
/// The provided name is empty or invalid.
InvalidName,
/// The specified user was not found.
UserNotFound,
/// Authentication failed (wrong password).
AuthenticationFailed,
/// The user account is deactivated.
AccountDeactivated,
}
impl std::fmt::Display for UserError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UserError::InvalidEmail => write!(f, "Invalid email address format"),
UserError::DuplicateEmail => write!(f, "User with this email already exists"),
UserError::InvalidName => write!(f, "Invalid or empty name"),
UserError::UserNotFound => write!(f, "User not found"),
UserError::AuthenticationFailed => write!(f, "Authentication failed"),
UserError::AccountDeactivated => write!(f, "User account is deactivated"),
}
}
}
impl std::error::Error for UserError {}
Documentation Linting
# In Cargo.toml
[lints.rustdoc]
# Warn about missing documentation
missing_docs = "warn"
# Warn about broken intra-doc links
broken_intra_doc_links = "warn"
# Warn about invalid code blocks in documentation
invalid_codeblock_attributes = "warn"
[package.metadata.docs.rs]
# Configuration for docs.rs
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
// Enable documentation lints
#![warn(missing_docs)]
#![warn(rustdoc::broken_intra_doc_links)]
#![warn(rustdoc::private_intra_doc_links)]
/// This function links to [`UserManager`] and [`UserError`].
///
/// You can also link to methods like [`UserManager::create_user`]
/// or even external crates like [`std::collections::HashMap`].
///
/// For linking to modules, use [`crate::geometry`] or [`super::arithmetic`].
pub fn example_with_links() {
// Function implementation
}
Documentation is crucial for making Rust code accessible and maintainable. Use rustdoc
features extensively, write comprehensive examples, and keep documentation up-to-date with code changes. Good documentation serves as both user guide and API reference, making your crate easier to adopt and contribute to.