1use crate::core::*;
7use crate::error::{MemoryError, Result};
8use chrono::{DateTime, Duration, Timelike, Utc};
9use flate2::{read::GzDecoder, write::GzEncoder, Compression};
10use serde::{Deserialize, Serialize};
11use sha2::{Digest, Sha256};
12use std::collections::{HashMap, HashSet};
13use std::io::{Read, Write};
14use uuid::Uuid;
15
16pub struct VectorUtils;
18
19pub struct TextUtils;
21
22pub struct TimeUtils;
24
25pub struct SerializationUtils;
27
28pub struct CacheUtils;
30
31pub struct HashUtils;
33
34pub struct IdGenerator;
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct SimilarityResult {
40 pub score: f32,
41 pub method: SimilarityMethod,
42 pub details: HashMap<String, f32>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub enum SimilarityMethod {
48 Cosine,
49 Euclidean,
50 Manhattan,
51 Jaccard,
52 Semantic,
53 Hybrid,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct TextStats {
59 pub char_count: usize,
60 pub word_count: usize,
61 pub sentence_count: usize,
62 pub paragraph_count: usize,
63 pub language: Option<String>,
64 pub complexity_score: f32,
65 pub readability_score: f32,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct TimeRange {
71 pub start: DateTime<Utc>,
72 pub end: DateTime<Utc>,
73}
74
75#[derive(Debug, Clone)]
77pub struct CompressionResult {
78 pub compressed_data: Vec<u8>,
79 pub original_size: usize,
80 pub compressed_size: usize,
81 pub compression_ratio: f32,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct CacheStats {
87 pub hit_count: u64,
88 pub miss_count: u64,
89 pub hit_rate: f32,
90 pub total_size: usize,
91 pub entry_count: usize,
92 pub last_cleanup: Option<DateTime<Utc>>,
93}
94
95impl VectorUtils {
96 pub fn cosine_similarity(a: &[f32], b: &[f32]) -> Result<f32> {
98 if a.len() != b.len() {
99 return Err(MemoryError::InvalidVectorDimension {
100 expected: a.len(),
101 actual: b.len(),
102 });
103 }
104
105 if a.is_empty() {
106 return Ok(0.0);
107 }
108
109 let dot_product: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
110 let norm_a: f32 = a.iter().map(|x| x * x).sum::<f32>().sqrt();
111 let norm_b: f32 = b.iter().map(|x| x * x).sum::<f32>().sqrt();
112
113 if norm_a == 0.0 || norm_b == 0.0 {
114 return Ok(0.0);
115 }
116
117 Ok(dot_product / (norm_a * norm_b))
118 }
119
120 pub fn euclidean_distance(a: &[f32], b: &[f32]) -> Result<f32> {
122 if a.len() != b.len() {
123 return Err(MemoryError::InvalidVectorDimension {
124 expected: a.len(),
125 actual: b.len(),
126 });
127 }
128
129 let distance: f32 = a
130 .iter()
131 .zip(b.iter())
132 .map(|(x, y)| (x - y).powi(2))
133 .sum::<f32>()
134 .sqrt();
135
136 Ok(distance)
137 }
138
139 pub fn manhattan_distance(a: &[f32], b: &[f32]) -> Result<f32> {
141 if a.len() != b.len() {
142 return Err(MemoryError::InvalidVectorDimension {
143 expected: a.len(),
144 actual: b.len(),
145 });
146 }
147
148 let distance: f32 = a.iter().zip(b.iter()).map(|(x, y)| (x - y).abs()).sum();
149
150 Ok(distance)
151 }
152
153 pub fn normalize(vector: &mut [f32]) -> Result<()> {
155 let norm: f32 = vector.iter().map(|x| x * x).sum::<f32>().sqrt();
156
157 if norm == 0.0 {
158 return Err(MemoryError::Internal {
159 message: "Cannot normalize zero vector".to_string(),
160 });
161 }
162
163 for value in vector.iter_mut() {
164 *value /= norm;
165 }
166
167 Ok(())
168 }
169
170 pub fn weighted_average(vectors: &[Vec<f32>], weights: &[f32]) -> Result<Vec<f32>> {
172 if vectors.is_empty() {
173 return Err(MemoryError::Internal {
174 message: "No vectors provided".to_string(),
175 });
176 }
177
178 if vectors.len() != weights.len() {
179 return Err(MemoryError::Internal {
180 message: "Vector and weight count mismatch".to_string(),
181 });
182 }
183
184 let dim = vectors[0].len();
185 if !vectors.iter().all(|v| v.len() == dim) {
186 return Err(MemoryError::Internal {
187 message: "Inconsistent vector dimensions".to_string(),
188 });
189 }
190
191 let weight_sum: f32 = weights.iter().sum();
192 if weight_sum == 0.0 {
193 return Err(MemoryError::Internal {
194 message: "Zero weight sum".to_string(),
195 });
196 }
197
198 let mut result = vec![0.0; dim];
199 for (vector, &weight) in vectors.iter().zip(weights.iter()) {
200 for (i, &value) in vector.iter().enumerate() {
201 result[i] += value * weight / weight_sum;
202 }
203 }
204
205 Ok(result)
206 }
207
208 pub fn centroid(vectors: &[Vec<f32>]) -> Result<Vec<f32>> {
210 if vectors.is_empty() {
211 return Err(MemoryError::Internal {
212 message: "No vectors provided".to_string(),
213 });
214 }
215
216 let weights = vec![1.0; vectors.len()];
217 Self::weighted_average(vectors, &weights)
218 }
219
220 pub fn quantize(vector: &[f32], levels: u8) -> Vec<u8> {
222 let min_val = vector.iter().fold(f32::INFINITY, |a, &b| a.min(b));
223 let max_val = vector.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
224 let range = max_val - min_val;
225
226 if range == 0.0 {
227 return vec![0; vector.len()];
228 }
229
230 let scale = (levels - 1) as f32 / range;
231
232 vector
233 .iter()
234 .map(|&val| ((val - min_val) * scale).round() as u8)
235 .collect()
236 }
237
238 pub fn dequantize(quantized: &[u8], min_val: f32, max_val: f32, levels: u8) -> Vec<f32> {
240 let range = max_val - min_val;
241 let scale = range / (levels - 1) as f32;
242
243 quantized
244 .iter()
245 .map(|&val| min_val + val as f32 * scale)
246 .collect()
247 }
248}
249
250impl TextUtils {
251 pub fn analyze_text(text: &str) -> TextStats {
253 let char_count = text.chars().count();
254 let word_count = text.split_whitespace().count();
255 let sentence_count = if text.trim().is_empty() {
257 0
258 } else {
259 let english_count = text.matches(&['.', '!', '?'][..]).count();
261 let chinese_count = text.matches(&['。', '!', '?'][..]).count();
262 let total_count = english_count + chinese_count;
263 if total_count == 0 {
264 1 } else {
266 total_count
267 }
268 };
269 let paragraph_count = text
270 .split("\n\n")
271 .filter(|p| !p.trim().is_empty())
272 .count()
273 .max(1);
274
275 let complexity_score = Self::calculate_complexity(text);
276 let readability_score = Self::calculate_readability(text, word_count, sentence_count);
277 let language = Self::detect_language(text);
278
279 TextStats {
280 char_count,
281 word_count,
282 sentence_count,
283 paragraph_count,
284 language,
285 complexity_score,
286 readability_score,
287 }
288 }
289
290 fn calculate_complexity(text: &str) -> f32 {
292 let words: Vec<&str> = text.split_whitespace().collect();
293 if words.is_empty() {
294 return 0.0;
295 }
296
297 let avg_word_length: f32 = words
298 .iter()
299 .map(|word| word.chars().count() as f32)
300 .sum::<f32>()
301 / words.len() as f32;
302
303 let unique_words: HashSet<&str> = words.iter().cloned().collect();
304 let vocabulary_diversity = unique_words.len() as f32 / words.len() as f32;
305
306 (avg_word_length / 10.0 + vocabulary_diversity) / 2.0
308 }
309
310 fn calculate_readability(text: &str, word_count: usize, sentence_count: usize) -> f32 {
312 if word_count == 0 || sentence_count == 0 {
313 return 0.0;
314 }
315
316 let syllable_count = Self::estimate_syllables(text);
317 let avg_sentence_length = word_count as f32 / sentence_count as f32;
318 let avg_syllables_per_word = syllable_count as f32 / word_count as f32;
319
320 206.835 - (1.015 * avg_sentence_length) - (84.6 * avg_syllables_per_word)
322 }
323
324 fn estimate_syllables(text: &str) -> usize {
326 let vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
327 let mut syllable_count = 0;
328
329 for word in text.split_whitespace() {
330 let word = word.to_lowercase();
331 let mut word_syllables = 0;
332 let mut prev_was_vowel = false;
333
334 for ch in word.chars() {
335 let is_vowel = vowels.contains(&ch);
336 if is_vowel && !prev_was_vowel {
337 word_syllables += 1;
338 }
339 prev_was_vowel = is_vowel;
340 }
341
342 syllable_count += word_syllables.max(1);
344 }
345
346 syllable_count
347 }
348
349 fn detect_language(text: &str) -> Option<String> {
351 let chinese_chars = text
352 .chars()
353 .filter(|c| {
354 let code = *c as u32;
355 (0x4E00..=0x9FFF).contains(&code) })
357 .count();
358
359 let total_chars = text.chars().filter(|c| c.is_alphabetic()).count();
360
361 if total_chars == 0 {
362 return None;
363 }
364
365 if chinese_chars as f32 / total_chars as f32 > 0.3 {
366 Some("zh".to_string())
367 } else {
368 Some("en".to_string())
369 }
370 }
371
372 pub fn extract_keywords(text: &str, max_keywords: usize) -> Vec<String> {
374 let stop_words: HashSet<&str> = [
375 "the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", "of", "with",
376 "by", "is", "are", "was", "were", "be", "been", "have", "has", "had", "do", "does",
377 "did", "will", "would", "could", "should", "的", "了", "在", "是", "我", "你", "他",
378 "她", "它", "们", "这", "那", "有", "和", "与", "或", "但", "如果", "因为", "所以",
379 "然后", "现在", "一个", "多个", "包含", "还有",
380 ]
381 .iter()
382 .cloned()
383 .collect();
384
385 let mut word_freq: HashMap<String, usize> = HashMap::new();
386
387 let chinese_chars = text
389 .chars()
390 .filter(|c| {
391 let code = *c as u32;
392 (0x4E00..=0x9FFF).contains(&code)
393 })
394 .count();
395
396 if chinese_chars > text.chars().count() / 3 {
397 for word in text.split_whitespace() {
399 let cleaned = word
400 .chars()
401 .filter(|c| c.is_alphanumeric())
402 .collect::<String>();
403
404 if cleaned.len() >= 2 && !stop_words.contains(cleaned.as_str()) {
405 *word_freq.entry(cleaned).or_insert(0) += 1;
406 }
407 }
408 } else {
409 for word in text.split_whitespace() {
411 let word = word
412 .to_lowercase()
413 .trim_matches(|c: char| !c.is_alphanumeric())
414 .to_string();
415
416 if word.len() > 2 && !stop_words.contains(word.as_str()) {
417 *word_freq.entry(word).or_insert(0) += 1;
418 }
419 }
420 }
421
422 let mut keywords: Vec<(String, usize)> = word_freq.into_iter().collect();
423 keywords.sort_by(|a, b| b.1.cmp(&a.1));
424
425 keywords
426 .into_iter()
427 .take(max_keywords)
428 .map(|(word, _)| word)
429 .collect()
430 }
431
432 pub fn jaccard_similarity(text1: &str, text2: &str) -> f32 {
434 let words1: HashSet<&str> = text1.split_whitespace().collect();
435 let words2: HashSet<&str> = text2.split_whitespace().collect();
436
437 if words1.is_empty() && words2.is_empty() {
438 return 1.0;
439 }
440
441 let intersection = words1.intersection(&words2).count();
442 let union = words1.union(&words2).count();
443
444 if union == 0 {
445 0.0
446 } else {
447 intersection as f32 / union as f32
448 }
449 }
450
451 pub fn summarize(text: &str, max_sentences: usize) -> String {
453 let sentences: Vec<&str> = text
454 .split(&['.', '!', '?'][..])
455 .filter(|s| !s.trim().is_empty())
456 .collect();
457
458 if sentences.len() <= max_sentences {
459 return text.to_string();
460 }
461
462 sentences
464 .iter()
465 .take(max_sentences)
466 .map(|s| s.trim())
467 .collect::<Vec<_>>()
468 .join(". ")
469 + "."
470 }
471}
472
473impl TimeUtils {
474 pub fn create_range(start: DateTime<Utc>, end: DateTime<Utc>) -> Result<TimeRange> {
476 if start > end {
477 return Err(MemoryError::Internal {
478 message: "Start time must be before end time".to_string(),
479 });
480 }
481
482 Ok(TimeRange { start, end })
483 }
484
485 pub fn is_in_range(time: DateTime<Utc>, range: &TimeRange) -> bool {
487 time >= range.start && time <= range.end
488 }
489
490 pub fn calculate_decay_factor(timestamp: DateTime<Utc>, half_life: Duration) -> f32 {
492 let elapsed = Utc::now() - timestamp;
493 let half_life_seconds = half_life.num_seconds() as f64;
494 let elapsed_seconds = elapsed.num_seconds() as f64;
495
496 if half_life_seconds <= 0.0 {
497 return 1.0;
498 }
499
500 (0.5_f64.powf(elapsed_seconds / half_life_seconds)) as f32
501 }
502
503 pub fn get_time_period_description(timestamp: DateTime<Utc>) -> String {
505 let now = Utc::now();
506 let diff = now - timestamp;
507
508 if diff < Duration::minutes(1) {
509 "刚刚".to_string()
510 } else if diff < Duration::hours(1) {
511 format!("{}分钟前", diff.num_minutes())
512 } else if diff < Duration::days(1) {
513 format!("{}小时前", diff.num_hours())
514 } else if diff < Duration::days(7) {
515 format!("{}天前", diff.num_days())
516 } else if diff < Duration::days(30) {
517 format!("{}周前", diff.num_weeks())
518 } else if diff < Duration::days(365) {
519 format!("{}个月前", diff.num_days() / 30)
520 } else {
521 format!("{}年前", diff.num_days() / 365)
522 }
523 }
524
525 pub fn get_time_of_day_period(timestamp: DateTime<Utc>) -> String {
527 let hour = timestamp.hour();
528
529 match hour {
530 5..=11 => "上午".to_string(),
531 12..=17 => "下午".to_string(),
532 18..=22 => "晚上".to_string(),
533 _ => "深夜".to_string(),
534 }
535 }
536
537 pub fn temporal_similarity(
539 time1: DateTime<Utc>,
540 time2: DateTime<Utc>,
541 window: Duration,
542 ) -> f32 {
543 let diff = (time1 - time2).abs();
544 let window_seconds = window.num_seconds() as f64;
545 let diff_seconds = diff.num_seconds() as f64;
546
547 if diff_seconds >= window_seconds {
548 0.0
549 } else {
550 1.0 - (diff_seconds / window_seconds) as f32
551 }
552 }
553}
554
555impl SerializationUtils {
556 pub fn compress(data: &[u8]) -> Result<CompressionResult> {
558 let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
559 encoder.write_all(data).map_err(MemoryError::Io)?;
560
561 let compressed_data = encoder.finish().map_err(MemoryError::Io)?;
562
563 let original_size = data.len();
564 let compressed_size = compressed_data.len();
565 let compression_ratio = if original_size > 0 {
566 compressed_size as f32 / original_size as f32
567 } else {
568 1.0
569 };
570
571 Ok(CompressionResult {
572 compressed_data,
573 original_size,
574 compressed_size,
575 compression_ratio,
576 })
577 }
578
579 pub fn decompress(compressed_data: &[u8]) -> Result<Vec<u8>> {
581 let mut decoder = GzDecoder::new(compressed_data);
582 let mut decompressed = Vec::new();
583
584 decoder
585 .read_to_end(&mut decompressed)
586 .map_err(MemoryError::Io)?;
587
588 Ok(decompressed)
589 }
590
591 pub fn to_json<T: Serialize>(data: &T) -> Result<String> {
593 serde_json::to_string(data).map_err(MemoryError::Serialization)
594 }
595
596 pub fn from_json<T: for<'de> Deserialize<'de>>(json: &str) -> Result<T> {
598 serde_json::from_str(json).map_err(MemoryError::Serialization)
599 }
600
601 pub fn to_binary<T: Serialize + bincode::Encode>(data: &T) -> Result<Vec<u8>> {
603 bincode::encode_to_vec(data, bincode::config::standard()).map_err(|e| {
604 MemoryError::Internal {
605 message: format!("Binary serialization failed: {}", e),
606 }
607 })
608 }
609
610 pub fn from_binary<T: for<'de> Deserialize<'de> + bincode::Decode<()>>(
612 data: &[u8],
613 ) -> Result<T> {
614 bincode::decode_from_slice(data, bincode::config::standard())
615 .map(|(result, _)| result)
616 .map_err(|e| MemoryError::Internal {
617 message: format!("Binary deserialization failed: {}", e),
618 })
619 }
620}
621
622impl CacheUtils {
623 pub fn calculate_hit_rate(hit_count: u64, miss_count: u64) -> f32 {
625 let total = hit_count + miss_count;
626 if total == 0 {
627 0.0
628 } else {
629 hit_count as f32 / total as f32
630 }
631 }
632
633 pub fn estimate_memory_usage<T>(items: &[T]) -> usize {
635 std::mem::size_of_val(items)
636 }
637
638 pub fn generate_cache_key(components: &[&str]) -> String {
640 let mut hasher = Sha256::new();
641 for component in components {
642 hasher.update(component.as_bytes());
643 }
644 format!("{:x}", hasher.finalize())
645 }
646
647 pub fn should_cleanup(last_cleanup: Option<DateTime<Utc>>, interval: Duration) -> bool {
649 match last_cleanup {
650 Some(last) => Utc::now() - last > interval,
651 None => true,
652 }
653 }
654}
655
656impl HashUtils {
657 pub fn hash_string(input: &str) -> String {
659 let mut hasher = Sha256::new();
660 hasher.update(input.as_bytes());
661 format!("{:x}", hasher.finalize())
662 }
663
664 pub fn hash_bytes(data: &[u8]) -> String {
666 let mut hasher = Sha256::new();
667 hasher.update(data);
668 format!("{:x}", hasher.finalize())
669 }
670
671 pub fn short_hash(input: &str, length: usize) -> String {
673 let full_hash = Self::hash_string(input);
674 full_hash
675 .chars()
676 .take(length.min(full_hash.len()))
677 .collect()
678 }
679
680 pub fn verify_hash(input: &str, expected_hash: &str) -> bool {
682 Self::hash_string(input) == expected_hash
683 }
684}
685
686impl IdGenerator {
687 pub fn generate_memory_id() -> MemoryId {
689 format!("mem_{}", Uuid::new_v4())
690 }
691
692 pub fn generate_connection_id() -> ConnectionId {
694 format!("conn_{}", Uuid::new_v4())
695 }
696
697 pub fn generate_session_id() -> String {
699 format!("session_{}", Uuid::new_v4())
700 }
701
702 pub fn generate_query_id() -> String {
704 format!("query_{}", Uuid::new_v4())
705 }
706
707 pub fn generate_interaction_id() -> String {
709 format!("interaction_{}", Uuid::new_v4())
710 }
711
712
713
714 pub fn generate_time_based_id(prefix: &str) -> String {
716 let timestamp = Utc::now().timestamp_millis();
717 let uuid = Uuid::new_v4();
718 format!("{}_{:x}_{}", prefix, timestamp, uuid.simple())
719 }
720
721 pub fn generate_short_id(length: usize) -> String {
723 let uuid = Uuid::new_v4();
724 uuid.simple().to_string().chars().take(length).collect()
725 }
726}
727
728pub struct BatchUtils;
730
731impl BatchUtils {
732 pub fn chunk<T: Clone>(data: Vec<T>, chunk_size: usize) -> Vec<Vec<T>> {
734 if chunk_size == 0 {
735 return vec![data];
736 }
737
738 data.chunks(chunk_size)
739 .map(|chunk| chunk.to_vec())
740 .collect()
741 }
742
743 pub async fn process_batches<T, F, R>(batches: Vec<Vec<T>>, processor: F) -> Vec<Result<R>>
745 where
746 T: Send + 'static,
747 F: Fn(Vec<T>) -> Result<R> + Send + Sync + 'static + Clone,
748 R: Send + 'static,
749 {
750 let mut handles = Vec::new();
751
752 for batch in batches {
753 let processor = processor.clone();
754 let handle = tokio::spawn(async move { processor(batch) });
755 handles.push(handle);
756 }
757
758 let mut results = Vec::new();
759 for handle in handles {
760 match handle.await {
761 Ok(result) => results.push(result),
762 Err(e) => results.push(Err(MemoryError::Internal {
763 message: e.to_string(),
764 })),
765 }
766 }
767
768 results
769 }
770}
771
772pub struct PerformanceUtils;
774
775impl PerformanceUtils {
776 pub async fn measure_time<F, T>(operation: F) -> (T, Duration)
778 where
779 F: std::future::Future<Output = T>,
780 {
781 let start = Utc::now();
782 let result = operation.await;
783 let duration = Utc::now() - start;
784 (result, duration)
785 }
786
787 pub fn create_performance_report(
789 operation_name: &str,
790 duration: Duration,
791 items_processed: usize,
792 ) -> HashMap<String, serde_json::Value> {
793 let mut report = HashMap::new();
794
795 report.insert(
796 "operation".to_string(),
797 serde_json::Value::String(operation_name.to_string()),
798 );
799 report.insert(
800 "duration_ms".to_string(),
801 serde_json::Value::Number(duration.num_milliseconds().into()),
802 );
803 report.insert(
804 "items_processed".to_string(),
805 serde_json::Value::Number(items_processed.into()),
806 );
807
808 if items_processed > 0 && duration.num_milliseconds() > 0 {
809 let throughput = items_processed as f64 / (duration.num_milliseconds() as f64 / 1000.0);
810 report.insert(
811 "throughput_per_second".to_string(),
812 serde_json::Value::Number(
813 serde_json::Number::from_f64(throughput).unwrap_or_else(|| 0.into()),
814 ),
815 );
816 }
817
818 report
819 }
820}
821
822#[cfg(test)]
823mod tests {
824 use super::*;
825
826 #[test]
827 fn test_vector_cosine_similarity() {
828 let a = vec![1.0, 2.0, 3.0];
829 let b = vec![4.0, 5.0, 6.0];
830
831 let similarity = VectorUtils::cosine_similarity(&a, &b).unwrap();
832 assert!(similarity > 0.9); }
834
835 #[test]
836 fn test_vector_normalization() {
837 let mut vector = vec![3.0, 4.0];
838 VectorUtils::normalize(&mut vector).unwrap();
839
840 let norm: f32 = vector.iter().map(|x| x * x).sum::<f32>().sqrt();
841 assert!((norm - 1.0).abs() < 1e-6);
842 }
843
844 #[test]
845 fn test_text_analysis() {
846 let text = "这是一个测试文本。它包含多个句子!还有问号吗?";
847 let stats = TextUtils::analyze_text(text);
848
849 assert!(stats.char_count > 0);
850 assert!(stats.word_count > 0);
851 assert_eq!(stats.sentence_count, 3);
852 assert_eq!(stats.language, Some("zh".to_string()));
853 }
854
855 #[test]
856 fn test_keyword_extraction() {
857 let text = "机器学习是人工智能的一个重要分支。深度学习是机器学习的子领域。";
858 let keywords = TextUtils::extract_keywords(text, 3);
859
860 assert!(!keywords.is_empty());
861 assert!(keywords.len() > 0);
862 }
863
864 #[test]
865 fn test_time_decay() {
866 let now = Utc::now();
867 let past = now - Duration::hours(1);
868 let half_life = Duration::hours(2);
869
870 let decay = TimeUtils::calculate_decay_factor(past, half_life);
871 assert!(decay > 0.7 && decay < 0.8); }
873
874 #[test]
875 fn test_compression() {
876 let data = "这是一些测试数据,应该可以被压缩。重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容。".as_bytes();
878 let result = SerializationUtils::compress(data).unwrap();
879
880 assert!(result.compressed_size <= result.original_size);
882 assert!(result.compression_ratio <= 1.0);
883
884 let decompressed = SerializationUtils::decompress(&result.compressed_data).unwrap();
885 assert_eq!(data, decompressed.as_slice());
886 }
887
888 #[test]
889 fn test_hash_generation() {
890 let input = "测试字符串";
891 let hash1 = HashUtils::hash_string(input);
892 let hash2 = HashUtils::hash_string(input);
893
894 assert_eq!(hash1, hash2); assert_eq!(hash1.len(), 64); let short_hash = HashUtils::short_hash(input, 8);
898 assert_eq!(short_hash.len(), 8);
899 }
900
901 #[test]
902 fn test_id_generation() {
903 let memory_id = IdGenerator::generate_memory_id();
904 let connection_id = IdGenerator::generate_connection_id();
905
906 assert!(memory_id.starts_with("mem_"));
907 assert!(connection_id.starts_with("conn_"));
908
909 let id1 = IdGenerator::generate_memory_id();
911 let id2 = IdGenerator::generate_memory_id();
912 assert_ne!(id1, id2);
913 }
914
915 #[test]
916 fn test_batch_chunking() {
917 let data: Vec<i32> = (1..=10).collect();
918 let chunks = BatchUtils::chunk(data, 3);
919
920 assert_eq!(chunks.len(), 4); assert_eq!(chunks[0], vec![1, 2, 3]);
922 assert_eq!(chunks[3], vec![10]); }
924
925 #[test]
926 fn test_cache_hit_rate() {
927 let hit_rate = CacheUtils::calculate_hit_rate(80, 20);
928 assert_eq!(hit_rate, 0.8);
929
930 let hit_rate_zero = CacheUtils::calculate_hit_rate(0, 0);
931 assert_eq!(hit_rate_zero, 0.0);
932 }
933
934 #[tokio::test]
935 async fn test_performance_measurement() {
936 let (result, duration) = PerformanceUtils::measure_time(async {
937 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
938 42
939 })
940 .await;
941
942 assert_eq!(result, 42);
943 assert!(duration.num_milliseconds() >= 100);
944 }
945}