commitbee 0.6.0

AI-powered commit message generator using tree-sitter semantic analysis and local LLMs
Documentation
diff --git a/src/services/large.rs b/src/services/large.rs
new file mode 100644
index 0000000..abc1234
--- /dev/null
+++ b/src/services/large.rs
@@ -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);
+    }
+}