use std::sync::{Arc, RwLock};
pub mod cache;
pub mod lazy_loader;
pub mod memory_mapped;
pub mod stream_processor;
pub use cache::{LruCache, ObjectCache};
pub use lazy_loader::{LazyDocument, LazyObject};
pub use memory_mapped::{MappedReader, MemoryMappedFile};
pub use stream_processor::{ProcessingAction, ProcessingEvent, StreamProcessor, StreamingOptions};
#[derive(Debug, Clone)]
pub struct MemoryOptions {
pub lazy_loading: bool,
pub memory_mapping: bool,
pub cache_size: usize,
pub streaming: bool,
pub buffer_size: usize,
pub mmap_threshold: usize,
}
impl Default for MemoryOptions {
fn default() -> Self {
Self {
lazy_loading: true,
memory_mapping: true,
cache_size: 1000,
streaming: true,
buffer_size: 64 * 1024, mmap_threshold: 10 * 1024 * 1024, }
}
}
impl MemoryOptions {
pub fn small_file() -> Self {
Self {
lazy_loading: false,
memory_mapping: false,
cache_size: 0,
streaming: false,
buffer_size: 16 * 1024,
mmap_threshold: usize::MAX,
}
}
pub fn large_file() -> Self {
Self {
lazy_loading: true,
memory_mapping: true,
cache_size: 5000,
streaming: true,
buffer_size: 256 * 1024,
mmap_threshold: 1024 * 1024, }
}
pub fn with_lazy_loading(mut self, enabled: bool) -> Self {
self.lazy_loading = enabled;
self
}
pub fn with_memory_mapping(mut self, enabled: bool) -> Self {
self.memory_mapping = enabled;
self
}
pub fn with_cache_size(mut self, size: usize) -> Self {
self.cache_size = size;
self
}
pub fn with_streaming(mut self, enabled: bool) -> Self {
self.streaming = enabled;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct MemoryStats {
pub allocated_bytes: usize,
pub cached_objects: usize,
pub cache_hits: usize,
pub cache_misses: usize,
pub lazy_loads: usize,
pub mapped_regions: usize,
}
pub struct MemoryManager {
#[allow(dead_code)]
options: MemoryOptions,
stats: Arc<RwLock<MemoryStats>>,
cache: Option<ObjectCache>,
}
impl MemoryManager {
pub fn new(options: MemoryOptions) -> Self {
let cache = if options.cache_size > 0 {
Some(ObjectCache::new(options.cache_size))
} else {
None
};
Self {
options,
stats: Arc::new(RwLock::new(MemoryStats::default())),
cache,
}
}
pub fn stats(&self) -> MemoryStats {
self.stats
.read()
.map(|stats| stats.clone())
.unwrap_or_else(|_| MemoryStats::default())
}
pub fn record_allocation(&self, bytes: usize) {
if let Ok(mut stats) = self.stats.write() {
stats.allocated_bytes += bytes;
}
}
pub fn record_cache_hit(&self) {
if let Ok(mut stats) = self.stats.write() {
stats.cache_hits += 1;
}
}
pub fn record_cache_miss(&self) {
if let Ok(mut stats) = self.stats.write() {
stats.cache_misses += 1;
}
}
pub fn cache(&self) -> Option<&ObjectCache> {
self.cache.as_ref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_memory_options_default() {
let options = MemoryOptions::default();
assert!(options.lazy_loading);
assert!(options.memory_mapping);
assert_eq!(options.cache_size, 1000);
assert!(options.streaming);
assert_eq!(options.buffer_size, 64 * 1024);
}
#[test]
fn test_memory_options_small_file() {
let options = MemoryOptions::small_file();
assert!(!options.lazy_loading);
assert!(!options.memory_mapping);
assert_eq!(options.cache_size, 0);
assert!(!options.streaming);
}
#[test]
fn test_memory_options_large_file() {
let options = MemoryOptions::large_file();
assert!(options.lazy_loading);
assert!(options.memory_mapping);
assert_eq!(options.cache_size, 5000);
assert!(options.streaming);
assert_eq!(options.buffer_size, 256 * 1024);
}
#[test]
fn test_memory_options_builder() {
let options = MemoryOptions::default()
.with_lazy_loading(false)
.with_memory_mapping(false)
.with_cache_size(500)
.with_streaming(false);
assert!(!options.lazy_loading);
assert!(!options.memory_mapping);
assert_eq!(options.cache_size, 500);
assert!(!options.streaming);
}
#[test]
fn test_memory_stats() {
let stats = MemoryStats::default();
assert_eq!(stats.allocated_bytes, 0);
assert_eq!(stats.cached_objects, 0);
assert_eq!(stats.cache_hits, 0);
assert_eq!(stats.cache_misses, 0);
assert_eq!(stats.lazy_loads, 0);
assert_eq!(stats.mapped_regions, 0);
}
#[test]
fn test_memory_manager() {
let options = MemoryOptions::default();
let manager = MemoryManager::new(options);
manager.record_allocation(1024);
manager.record_cache_hit();
manager.record_cache_miss();
let stats = manager.stats();
assert_eq!(stats.allocated_bytes, 1024);
assert_eq!(stats.cache_hits, 1);
assert_eq!(stats.cache_misses, 1);
assert!(manager.cache().is_some());
}
#[test]
fn test_memory_manager_no_cache() {
let options = MemoryOptions::default().with_cache_size(0);
let manager = MemoryManager::new(options);
assert!(manager.cache().is_none());
}
}