reovim-protocol 0.14.4

Wire protocol types for reovim client-server communication
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
//! Debug RPC types for state inspection and diagnostics.
//!
//! This module contains types for debug endpoints that provide
//! runtime information, performance metrics, and log access.

use serde::{Deserialize, Serialize};

use super::types::Position;

// ============================================================================
// Phase 1: Foundation Types
// ============================================================================

/// Result for `debug/version` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VersionResult {
    /// Semantic version string (e.g., "0.9.0").
    pub version: String,
    /// Git commit hash (short form, e.g., "abc1234").
    #[serde(skip_serializing_if = "Option::is_none")]
    pub git_hash: Option<String>,
    /// Git commit hash (full 40-char form).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub git_commit: Option<String>,
    /// Whether the working directory has uncommitted changes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub git_dirty: Option<bool>,
    /// Build date in ISO 8601 format (date only, legacy).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub build_date: Option<String>,
    /// Build timestamp in full ISO 8601 format (with time).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub build_timestamp: Option<String>,
    /// Rust version used for compilation.
    pub rust_version: String,
    /// Target triple (e.g., "x86_64-unknown-linux-gnu").
    #[serde(skip_serializing_if = "Option::is_none")]
    pub target: Option<String>,
}

/// Result for `debug/uptime` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UptimeResult {
    /// Uptime in seconds (float for sub-second precision).
    pub uptime_seconds: f64,
    /// Human-readable uptime string (e.g., "1h 23m 45s").
    pub uptime_human: String,
    /// Server start time in ISO 8601 format.
    pub start_time: String,
}

// ============================================================================
// Phase 2: Inspection Types
// ============================================================================

/// Result for `debug/kernel_state` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KernelStateResult {
    /// Number of buffers currently loaded.
    pub buffer_count: usize,
    /// ID of the active buffer, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub active_buffer: Option<usize>,
    /// List of all buffer IDs.
    pub buffer_ids: Vec<usize>,
    /// Number of event handlers registered.
    pub event_handlers: usize,
    /// Number of events in the queue.
    pub event_queue_len: usize,
}

/// Yank type for registers.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum YankType {
    /// Characterwise yank.
    Characterwise,
    /// Linewise yank.
    Linewise,
}

/// A single register entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegisterEntry {
    /// Register name ('"' for unnamed, 'a'-'z' for named).
    pub name: String,
    /// Register content (may be truncated for large values).
    pub content: String,
    /// Original content length before truncation.
    pub content_length: usize,
    /// Type of yank operation.
    pub yank_type: YankType,
}

/// Result for `debug/registers` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegistersResult {
    /// Unnamed register (").
    pub unnamed: RegisterEntry,
    /// Named registers (a-z), only non-empty ones.
    pub named: Vec<RegisterEntry>,
}

/// A single mark entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarkEntry {
    /// Mark name ('a'-'z' for local, 'A'-'Z' for global, special chars for special marks).
    pub name: String,
    /// Position of the mark.
    pub position: Position,
    /// Buffer ID for global marks.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub buffer_id: Option<usize>,
}

/// Result for `debug/marks` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarksResult {
    /// Local marks (a-z) for current buffer.
    pub local: Vec<MarkEntry>,
    /// Global marks (A-Z) across all buffers.
    pub global: Vec<MarkEntry>,
    /// Special marks ('.', '^', etc.).
    pub special: Vec<MarkEntry>,
}

/// Result for `debug/mode_stack` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModeStackResult {
    /// Current active mode display name.
    pub current: String,
    /// Full mode stack (bottom to top).
    pub stack: Vec<String>,
    /// Stack depth.
    pub depth: usize,
}

// ============================================================================
// Phase 3: Metrics Types
// ============================================================================

/// A single metric entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricEntry {
    /// Metric name.
    pub name: String,
    /// Metric value.
    pub value: u64,
}

/// Result for `debug/metrics` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsResult {
    /// Server uptime in seconds.
    pub uptime_seconds: f64,
    /// Total RPC requests handled.
    pub total_requests: u64,
    /// Counter metrics.
    pub counters: Vec<MetricEntry>,
}

/// Handler statistics entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HandlerStats {
    /// Handler method name.
    pub method: String,
    /// Total number of calls.
    pub call_count: u64,
    /// Total time spent in microseconds.
    pub total_micros: u64,
    /// Average time per call in microseconds.
    pub avg_micros: f64,
}

/// Result for `debug/handlers` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HandlersResult {
    /// Statistics for each handler.
    pub handlers: Vec<HandlerStats>,
}

// ============================================================================
// Phase 4: Log Access Types
// ============================================================================

/// Parameters for `debug/log_level` method.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LogLevelParams {
    /// New log level to set (None = get current level).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<String>,
}

/// Result for `debug/log_level` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogLevelResult {
    /// Current log level.
    pub level: String,
    /// Previous log level (only when setting).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub previous: Option<String>,
}

/// Parameters for `debug/log_tail` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogTailParams {
    /// Number of log entries to return (default: 50).
    #[serde(default = "default_log_count")]
    pub count: usize,

    /// Filter by minimum log level (trace, debug, info, warn, error).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<String>,

    /// Filter by target module (substring match).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub target: Option<String>,

    /// Filter by message content (substring match, case-insensitive).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub grep: Option<String>,
}

const fn default_log_count() -> usize {
    50
}

impl Default for LogTailParams {
    fn default() -> Self {
        Self {
            count: default_log_count(),
            level: None,
            target: None,
            grep: None,
        }
    }
}

/// A single log entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEntryResult {
    /// Timestamp in ISO 8601 format.
    pub timestamp: String,
    /// Log level (error, warn, info, debug, trace).
    pub level: String,
    /// Target module.
    pub target: String,
    /// Log message.
    pub message: String,
}

/// Result for `debug/log_tail` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogTailResult {
    /// Log entries (newest first).
    pub entries: Vec<LogEntryResult>,
    /// Number of entries dropped due to buffer overflow.
    pub overflow_count: u64,
}

/// Parameters for `debug/log_subscribe` method.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LogSubscribeParams {
    /// Minimum log level to receive (default: info).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<String>,
}

/// Result for `debug/log_subscribe` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogSubscribeResult {
    /// Unique subscription ID for unsubscribing.
    pub subscription_id: u64,
}

/// Parameters for `debug/log_unsubscribe` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogUnsubscribeParams {
    /// Subscription ID to cancel.
    pub subscription_id: u64,
}

/// Result for `debug/log_unsubscribe` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogUnsubscribeResult {
    /// Whether the subscription was found and removed.
    pub success: bool,
}

// ============================================================================
// Phase 5: Visual Debug Types
// ============================================================================

/// Server information section.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotServerSection {
    /// Server version.
    pub version: String,
    /// Uptime in seconds.
    pub uptime_seconds: f64,
    /// Session ID.
    pub session_id: String,
    /// Number of connected clients.
    pub client_count: usize,
}

/// Editor state section.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotEditorSection {
    /// Current mode.
    pub mode: String,
    /// Cursor position.
    pub cursor: Position,
    /// Selection info (if active).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub selection: Option<SnapshotSelectionInfo>,
}

/// Selection info for snapshot.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotSelectionInfo {
    /// Selection mode (character, line, block).
    pub mode: String,
    /// Anchor position.
    pub anchor: Position,
    /// Cursor position.
    pub cursor: Position,
}

/// Buffer info for snapshot.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotBufferInfo {
    /// Buffer ID.
    pub id: usize,
    /// File path if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub file_path: Option<String>,
    /// Whether buffer is modified.
    pub modified: bool,
    /// Number of lines.
    pub line_count: usize,
    /// Preview of first few lines.
    pub preview: Vec<String>,
}

/// Buffers section for snapshot.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotBuffersSection {
    /// Total buffer count.
    pub count: usize,
    /// Active buffer ID.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub active_id: Option<usize>,
    /// Buffer info list.
    pub buffers: Vec<SnapshotBufferInfo>,
}

/// UI section for snapshot.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotUiSection {
    /// Screen width.
    pub width: u16,
    /// Screen height.
    pub height: u16,
    /// ASCII art representation of the screen.
    pub ascii_art: String,
}

/// Vim state section for snapshot.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotVimSection {
    /// Registers summary.
    pub registers: RegistersResult,
    /// Marks summary.
    pub marks: MarksResult,
    /// Mode stack.
    pub mode_stack: ModeStackResult,
}

/// Result for `debug/visual_snapshot` method.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VisualSnapshotResult {
    /// Schema version for compatibility.
    pub schema_version: String,
    /// Timestamp in ISO 8601 format.
    pub timestamp: String,
    /// Server information.
    pub server: SnapshotServerSection,
    /// Editor state.
    pub editor: SnapshotEditorSection,
    /// Buffer information.
    pub buffers: SnapshotBuffersSection,
    /// UI state.
    pub ui: SnapshotUiSection,
    /// Vim state (registers, marks, modes).
    pub vim: SnapshotVimSection,
    /// Performance metrics.
    pub metrics: MetricsResult,
}

#[cfg(test)]
#[path = "debug_tests.rs"]
mod tests;