Rust bindings for the Apache Portable Runtime (APR) library and the associated APR-Util library.
This crate provides safe Rust bindings to the Apache Portable Runtime (APR), a C library that forms the foundation of the Apache HTTP Server and other Apache projects. APR provides a predictable and consistent interface to underlying platform-specific implementations for:
- Memory management and pool allocation
- File and network I/O
- Process and thread management
- Time handling
- String manipulation
- Data structures (hash tables, arrays, etc.)
- Cryptographic functions
This crate is primarily useful when developing Rust bindings for C libraries that depend on APR. Many Apache projects and other C libraries use APR for cross-platform compatibility and memory management. If you're creating Rust bindings for such libraries, this crate provides the necessary APR functionality with a safe Rust interface.
- Apache HTTP Server modules
- Subversion (SVN) libraries
- Apache Serf
- Any custom C library built on top of APR
- Safe Rust API: Wraps APR's C API with safe Rust abstractions
- Memory pools: APR's hierarchical memory management system
- Cross-platform: Inherits APR's platform abstraction layer
- Comprehensive coverage: Bindings for most commonly-used APR and APR-Util functionality
Add this to your Cargo.toml:
[dependencies]
apr = "0.3"You need to have APR and APR-Util installed on your system:
sudo apt-get install libapr1-dev libaprutil1-devsudo dnf install apr-devel apr-util-develbrew install apr apr-utilIf you need to build APR from source, download it from the Apache APR website.
APR uses memory pools for all memory allocation. This is fundamental when working with APR-based C libraries:
use apr::Pool;
fn main() -> apr::Result<()> {
// Create a root memory pool
let pool = Pool::new();
// Pools can have child pools for hierarchical memory management
let subpool = pool.create_subpool()?;
// Memory allocated from pools is automatically freed when the pool is dropped
Ok(())
}When creating bindings for C libraries that use APR, you'll typically need to:
- Initialize APR (handled automatically by this crate)
- Create memory pools for the C library to use
- Pass APR types between Rust and C
Example of integrating with a hypothetical APR-based C library:
use apr::{Pool, Status};
use std::ptr;
// Hypothetical C library that uses APR
extern "C" {
fn some_c_function(pool: *mut apr_sys::apr_pool_t) -> apr_sys::apr_status_t;
}
fn main() -> apr::Result<()> {
let pool = Pool::new();
// Get raw APR pool pointer to pass to C functions
let status = unsafe {
Status::from(some_c_function(pool.as_mut_ptr()))
};
if status.is_success() {
println!("C function succeeded!");
} else {
return Err(status.into());
}
Ok(())
}use apr::{Pool, file::File};
fn main() -> apr::Result<()> {
let pool = Pool::new();
// Open a file using APR
let file = File::open("example.txt", apr::file::Flag::READ, 0, &pool)?;
// Read file contents
let mut buffer = vec![0u8; 1024];
let bytes_read = file.read(&mut buffer)?;
println!("Read {} bytes", bytes_read);
Ok(())
}use apr::{Pool, hash::Hash};
fn main() -> apr::Result<()> {
let pool = Pool::new();
// Create a hash table
let mut hash = Hash::<String>::new(&pool);
// Insert key-value pairs
hash.set("key1", "value1".to_string());
hash.set("key2", "value2".to_string());
// Retrieve values
if let Some(value) = hash.get("key1") {
println!("Found: {}", value);
}
Ok(())
}The crate is organized into modules that mirror APR's structure:
pool- Memory pool managementfile- File I/O operationsnetwork- Network I/O and socket operationshash- Hash table implementationtables- APR table (ordered key-value pairs)strings- String manipulation utilitiestime- Time handling functionserror- Error handling and status codescrypto- Cryptographic functions (MD5, SHA1, etc.)base64- Base64 encoding/decodinguri- URI parsing and manipulationuuid- UUID generationxml- XML parsing utilities
This crate aims to provide safe Rust abstractions over APR's C API. However, when interfacing with C libraries:
- Some operations require
unsafeblocks when dealing with raw pointers - The crate handles APR initialization automatically using Rust's standard library features
- Memory management through pools helps prevent memory leaks
- Rust's ownership system is leveraged to ensure proper resource cleanup
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
When contributing, please:
- Add tests for new functionality
- Update documentation as needed
- Follow Rust naming conventions and idioms
- Ensure all tests pass with
cargo test
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- apr-sys - Low-level FFI bindings to APR (used by this crate)
- Apache APR - The underlying C library
For questions and discussions, please use the GitHub issues tracker.