vtcode_commons/
unicode.rs1#![expect(
2 unused_results,
3 reason = "Atomic metric updates are performed for their side effects; the previous counters are not needed."
4)]
5
6use hashbrown::HashMap;
9use once_cell::sync::Lazy;
10use std::sync::Mutex;
11use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
12use std::time::Instant;
13
14#[derive(Debug, Default)]
16pub struct UnicodeMonitor {
17 total_bytes_processed: AtomicU64,
19 total_unicode_bytes: AtomicU64,
20 total_sequences: AtomicU64,
21 total_errors: AtomicU64,
22
23 error_types: Mutex<HashMap<String, usize>>,
25 last_error: Mutex<Option<String>>,
26
27 processing_time_ns: AtomicU64,
29 max_buffer_size: AtomicUsize,
30
31 active_sessions: AtomicUsize,
33 total_sessions: AtomicUsize,
34 unicode_sessions: AtomicUsize,
35}
36
37impl UnicodeMonitor {
38 fn new() -> Self {
40 Self {
41 total_bytes_processed: AtomicU64::new(0),
42 total_unicode_bytes: AtomicU64::new(0),
43 total_sequences: AtomicU64::new(0),
44 total_errors: AtomicU64::new(0),
45 error_types: Mutex::new(HashMap::new()),
46 last_error: Mutex::new(None),
47 processing_time_ns: AtomicU64::new(0),
48 max_buffer_size: AtomicUsize::new(0),
49 active_sessions: AtomicUsize::new(0),
50 total_sessions: AtomicUsize::new(0),
51 unicode_sessions: AtomicUsize::new(0),
52 }
53 }
54
55 pub fn record_processing(&self, bytes: usize, unicode_bytes: usize, contains_unicode: bool) {
57 self.total_bytes_processed.fetch_add(bytes as u64, Ordering::Relaxed);
58 self.total_unicode_bytes.fetch_add(unicode_bytes as u64, Ordering::Relaxed);
59 self.total_sequences.fetch_add(1, Ordering::Relaxed);
60
61 if contains_unicode {
62 self.unicode_sessions.fetch_add(1, Ordering::Relaxed);
63 }
64 }
65
66 pub fn record_error(&self, error_type: &str, details: &str) {
68 self.total_errors.fetch_add(1, Ordering::Relaxed);
69
70 if let Ok(mut errors) = self.error_types.lock() {
71 *errors.entry(error_type.to_string()).or_insert(0) += 1;
72 }
73
74 if let Ok(mut last) = self.last_error.lock() {
75 *last = Some(format!("{error_type}: {details}"));
76 }
77 }
78
79 pub fn record_processing_time(&self, nanoseconds: u64) {
81 self.processing_time_ns.fetch_add(nanoseconds, Ordering::Relaxed);
82 }
83
84 pub fn record_max_buffer_size(&self, size: usize) {
86 self.max_buffer_size.fetch_max(size, Ordering::Relaxed);
87 }
88
89 pub fn start_session(&self) {
91 self.active_sessions.fetch_add(1, Ordering::Relaxed);
92 self.total_sessions.fetch_add(1, Ordering::Relaxed);
93 }
94
95 pub fn end_session(&self) {
97 self.active_sessions.fetch_sub(1, Ordering::Relaxed);
98 }
99}
100
101pub struct UnicodeValidationContext {
103 start_time: Instant,
104 unicode_detected: bool,
105 errors: Vec<String>,
106}
107
108impl UnicodeValidationContext {
109 pub fn new(_buffer_size: usize) -> Self {
111 Self {
112 start_time: Instant::now(),
113 unicode_detected: false,
114 errors: Vec::new(),
115 }
116 }
117
118 pub fn record_unicode_detected(&mut self) {
120 self.unicode_detected = true;
121 }
122
123 pub fn record_error(&mut self, error: String) {
125 self.errors.push(error);
126 }
127
128 pub fn complete(self, _processed_bytes: usize) {
130 }
132}
133
134pub static UNICODE_MONITOR: Lazy<UnicodeMonitor> = Lazy::new(UnicodeMonitor::new);