diff --git a/src/services/large.rs b/src/services/large.rs
new file mode 100644
index 0000000..abc1234
@@ -0,0 +1,200 @@
+use std::collections::HashMap;
+use crate::error::Result;
+
+/// A large module with many functions to test truncation behavior.
+pub struct LargeModule {
+ data: HashMap<String, Vec<u8>>,
+ cache: HashMap<String, String>,
+ counter: usize,
+ enabled: bool,
+}
+
+impl LargeModule {
+ pub fn new() -> Self {
+ Self {
+ data: HashMap::new(),
+ cache: HashMap::new(),
+ counter: 0,
+ enabled: true,
+ }
+ }
+
+ pub fn insert(&mut self, key: String, value: Vec<u8>) {
+ self.data.insert(key, value);
+ self.counter += 1;
+ }
+
+ pub fn get(&self, key: &str) -> Option<&Vec<u8>> {
+ self.data.get(key)
+ }
+
+ pub fn remove(&mut self, key: &str) -> Option<Vec<u8>> {
+ self.counter = self.counter.saturating_sub(1);
+ self.data.remove(key)
+ }
+
+ pub fn clear(&mut self) {
+ self.data.clear();
+ self.cache.clear();
+ self.counter = 0;
+ }
+
+ pub fn len(&self) -> usize {
+ self.data.len()
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.data.is_empty()
+ }
+
+ pub fn keys(&self) -> Vec<&String> {
+ self.data.keys().collect()
+ }
+
+ pub fn values(&self) -> Vec<&Vec<u8>> {
+ self.data.values().collect()
+ }
+
+ pub fn contains_key(&self, key: &str) -> bool {
+ self.data.contains_key(key)
+ }
+
+ pub fn cache_set(&mut self, key: String, value: String) {
+ self.cache.insert(key, value);
+ }
+
+ pub fn cache_get(&self, key: &str) -> Option<&String> {
+ self.cache.get(key)
+ }
+
+ pub fn cache_clear(&mut self) {
+ self.cache.clear();
+ }
+
+ pub fn enable(&mut self) {
+ self.enabled = true;
+ }
+
+ pub fn disable(&mut self) {
+ self.enabled = false;
+ }
+
+ pub fn is_enabled(&self) -> bool {
+ self.enabled
+ }
+
+ pub fn counter(&self) -> usize {
+ self.counter
+ }
+
+ pub fn reset_counter(&mut self) {
+ self.counter = 0;
+ }
+
+ fn internal_validate(&self, key: &str) -> bool {
+ !key.is_empty() && key.len() < 256
+ }
+
+ fn internal_transform(&self, data: &[u8]) -> Vec<u8> {
+ data.iter().map(|b| b.wrapping_add(1)).collect()
+ }
+
+ fn internal_hash(&self, data: &[u8]) -> u64 {
+ let mut hash: u64 = 0;
+ for byte in data {
+ hash = hash.wrapping_mul(31).wrapping_add(u64::from(*byte));
+ }
+ hash
+ }
+
+ pub fn process_batch(&mut self, items: Vec<(String, Vec<u8>)>) -> Result<usize> {
+ let mut count = 0;
+ for (key, value) in items {
+ if self.internal_validate(&key) {
+ let transformed = self.internal_transform(&value);
+ self.data.insert(key, transformed);
+ count += 1;
+ }
+ }
+ self.counter += count;
+ Ok(count)
+ }
+
+ pub fn export(&self) -> HashMap<String, Vec<u8>> {
+ self.data.clone()
+ }
+
+ pub fn import(&mut self, data: HashMap<String, Vec<u8>>) {
+ self.counter += data.len();
+ self.data.extend(data);
+ }
+
+ pub fn merge(&mut self, other: &LargeModule) {
+ for (key, value) in &other.data {
+ if !self.data.contains_key(key) {
+ self.data.insert(key.clone(), value.clone());
+ self.counter += 1;
+ }
+ }
+ }
+
+ pub fn diff(&self, other: &LargeModule) -> Vec<String> {
+ let mut differences = Vec::new();
+ for key in self.data.keys() {
+ if !other.data.contains_key(key) {
+ differences.push(format!("missing in other: {}", key));
+ }
+ }
+ for key in other.data.keys() {
+ if !self.data.contains_key(key) {
+ differences.push(format!("missing in self: {}", key));
+ }
+ }
+ differences
+ }
+
+ pub fn stats(&self) -> ModuleStats {
+ ModuleStats {
+ total_entries: self.data.len(),
+ total_bytes: self.data.values().map(|v| v.len()).sum(),
+ cache_entries: self.cache.len(),
+ counter: self.counter,
+ enabled: self.enabled,
+ }
+ }
+}
+
+pub struct ModuleStats {
+ pub total_entries: usize,
+ pub total_bytes: usize,
+ pub cache_entries: usize,
+ pub counter: usize,
+ pub enabled: bool,
+}
+
+impl std::fmt::Display for ModuleStats {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "entries={}, bytes={}, cache={}, counter={}, enabled={}",
+ self.total_entries,
+ self.total_bytes,
+ self.cache_entries,
+ self.counter,
+ self.enabled
+ )
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_insert_and_get() {
+ let mut module = LargeModule::new();
+ module.insert("key1".into(), vec![1, 2, 3]);
+ assert_eq!(module.get("key1"), Some(&vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_remove() {
+ let mut module = LargeModule::new();
+ module.insert("key1".into(), vec![1, 2, 3]);
+ let removed = module.remove("key1");
+ assert_eq!(removed, Some(vec![1, 2, 3]));
+ assert!(module.is_empty());
+ }
+
+ #[test]
+ fn test_clear() {
+ let mut module = LargeModule::new();
+ module.insert("key1".into(), vec![1]);
+ module.insert("key2".into(), vec![2]);
+ module.clear();
+ assert!(module.is_empty());
+ assert_eq!(module.counter(), 0);
+ }
+}