quantrs2_device/neutral_atom/
protocols.rs

1//! Communication protocols for neutral atom quantum devices
2//!
3//! This module provides protocol implementations for communicating with
4//! neutral atom quantum computers, including device discovery, command
5//! execution, and status monitoring.
6
7use crate::{DeviceError, DeviceResult};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::time::{Duration, SystemTime};
11
12/// Communication protocol types
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum ProtocolType {
15    /// HTTP/REST protocol
16    Http,
17    /// WebSocket protocol for real-time communication
18    WebSocket,
19    /// TCP/IP direct connection
20    Tcp,
21    /// USB serial connection
22    Serial,
23    /// Custom protocol
24    Custom(String),
25}
26
27/// Protocol configuration
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct ProtocolConfig {
30    /// Protocol type
31    pub protocol_type: ProtocolType,
32    /// Connection parameters
33    pub connection_params: ConnectionParams,
34    /// Authentication settings
35    pub authentication: AuthenticationConfig,
36    /// Timeout settings
37    pub timeouts: TimeoutConfig,
38    /// Retry configuration
39    pub retry_config: RetryConfig,
40}
41
42/// Connection parameters
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct ConnectionParams {
45    /// Host address
46    pub host: String,
47    /// Port number
48    pub port: u16,
49    /// Use secure connection (TLS/SSL)
50    pub secure: bool,
51    /// Connection endpoint path
52    pub endpoint: String,
53    /// Additional connection parameters
54    pub parameters: HashMap<String, String>,
55}
56
57/// Authentication configuration
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct AuthenticationConfig {
60    /// Authentication type
61    pub auth_type: AuthenticationType,
62    /// Username
63    pub username: Option<String>,
64    /// Password or token
65    pub credentials: Option<String>,
66    /// API key
67    pub api_key: Option<String>,
68    /// Certificate path for client certificates
69    pub certificate_path: Option<String>,
70}
71
72/// Authentication types
73#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
74pub enum AuthenticationType {
75    /// No authentication
76    None,
77    /// Basic authentication (username/password)
78    Basic,
79    /// Bearer token authentication
80    Bearer,
81    /// API key authentication
82    ApiKey,
83    /// Client certificate authentication
84    ClientCertificate,
85    /// Custom authentication method
86    Custom(String),
87}
88
89/// Timeout configuration
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct TimeoutConfig {
92    /// Connection timeout
93    pub connection_timeout: Duration,
94    /// Request timeout
95    pub request_timeout: Duration,
96    /// Response timeout
97    pub response_timeout: Duration,
98    /// Keep-alive timeout
99    pub keepalive_timeout: Duration,
100}
101
102/// Retry configuration
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct RetryConfig {
105    /// Maximum number of retries
106    pub max_retries: usize,
107    /// Initial retry delay
108    pub initial_delay: Duration,
109    /// Maximum retry delay
110    pub max_delay: Duration,
111    /// Backoff multiplier
112    pub backoff_multiplier: f64,
113    /// Jitter factor
114    pub jitter_factor: f64,
115}
116
117/// Protocol message types
118#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
119pub enum MessageType {
120    /// Device discovery request
121    Discovery,
122    /// Device status query
123    Status,
124    /// Circuit execution command
125    Execute,
126    /// Configuration update
127    Configure,
128    /// Calibration command
129    Calibrate,
130    /// Emergency stop
131    EmergencyStop,
132    /// Health check
133    HealthCheck,
134    /// Custom message
135    Custom(String),
136}
137
138/// Protocol message
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct ProtocolMessage {
141    /// Message ID
142    pub message_id: String,
143    /// Message type
144    pub message_type: MessageType,
145    /// Timestamp
146    pub timestamp: SystemTime,
147    /// Sender information
148    pub sender: String,
149    /// Recipient information
150    pub recipient: String,
151    /// Message payload
152    pub payload: HashMap<String, serde_json::Value>,
153    /// Priority level
154    pub priority: MessagePriority,
155}
156
157/// Message priority levels
158#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
159pub enum MessagePriority {
160    /// Low priority
161    Low,
162    /// Normal priority
163    Normal,
164    /// High priority
165    High,
166    /// Critical priority
167    Critical,
168}
169
170/// Protocol response
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct ProtocolResponse {
173    /// Response ID (matches request message ID)
174    pub response_id: String,
175    /// Response timestamp
176    pub timestamp: SystemTime,
177    /// Success status
178    pub success: bool,
179    /// Status code
180    pub status_code: u16,
181    /// Status message
182    pub status_message: String,
183    /// Response data
184    pub data: HashMap<String, serde_json::Value>,
185    /// Execution time
186    pub execution_time: Duration,
187}
188
189/// Device discovery protocol
190pub struct DeviceDiscoveryProtocol {
191    config: ProtocolConfig,
192    discovered_devices: Vec<DiscoveredDevice>,
193}
194
195/// Discovered device information
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct DiscoveredDevice {
198    /// Device ID
199    pub device_id: String,
200    /// Device name
201    pub device_name: String,
202    /// Device type
203    pub device_type: String,
204    /// Network address
205    pub address: String,
206    /// Port number
207    pub port: u16,
208    /// Device capabilities
209    pub capabilities: Vec<String>,
210    /// Device status
211    pub status: DeviceStatus,
212    /// Last seen timestamp
213    pub last_seen: SystemTime,
214}
215
216/// Device status
217#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
218pub enum DeviceStatus {
219    /// Device is online and available
220    Online,
221    /// Device is online but busy
222    Busy,
223    /// Device is offline
224    Offline,
225    /// Device is in maintenance mode
226    Maintenance,
227    /// Device is in error state
228    Error,
229    /// Unknown status
230    Unknown,
231}
232
233impl DeviceDiscoveryProtocol {
234    /// Create a new device discovery protocol
235    pub const fn new(config: ProtocolConfig) -> Self {
236        Self {
237            config,
238            discovered_devices: Vec::new(),
239        }
240    }
241
242    /// Discover available devices
243    pub async fn discover_devices(&mut self) -> DeviceResult<Vec<DiscoveredDevice>> {
244        // Implementation would depend on the specific protocol
245        // For now, return mock devices
246        let mock_device = DiscoveredDevice {
247            device_id: "neutral_atom_1".to_string(),
248            device_name: "Neutral Atom Device 1".to_string(),
249            device_type: "NeutralAtom".to_string(),
250            address: "192.168.1.100".to_string(),
251            port: 8080,
252            capabilities: vec![
253                "rydberg_gates".to_string(),
254                "optical_tweezers".to_string(),
255                "hyperfine_manipulation".to_string(),
256            ],
257            status: DeviceStatus::Online,
258            last_seen: SystemTime::now(),
259        };
260
261        self.discovered_devices = vec![mock_device.clone()];
262        Ok(vec![mock_device])
263    }
264
265    /// Get discovered devices
266    pub fn get_discovered_devices(&self) -> &[DiscoveredDevice] {
267        &self.discovered_devices
268    }
269
270    /// Refresh device status
271    pub async fn refresh_device_status(&mut self, device_id: &str) -> DeviceResult<DeviceStatus> {
272        // Find the device and update its status
273        for device in &mut self.discovered_devices {
274            if device.device_id == device_id {
275                // Mock status update
276                device.last_seen = SystemTime::now();
277                return Ok(device.status.clone());
278            }
279        }
280
281        Err(DeviceError::DeviceNotFound(format!(
282            "Device {device_id} not found"
283        )))
284    }
285}
286
287/// Command execution protocol
288pub struct CommandExecutionProtocol {
289    config: ProtocolConfig,
290    pending_commands: HashMap<String, PendingCommand>,
291}
292
293/// Pending command information
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct PendingCommand {
296    /// Command ID
297    pub command_id: String,
298    /// Command type
299    pub command_type: String,
300    /// Target device
301    pub target_device: String,
302    /// Command parameters
303    pub parameters: HashMap<String, serde_json::Value>,
304    /// Submission timestamp
305    pub submitted_at: SystemTime,
306    /// Expected completion time
307    pub expected_completion: Option<SystemTime>,
308    /// Current status
309    pub status: CommandStatus,
310}
311
312/// Command execution status
313#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
314pub enum CommandStatus {
315    /// Command is queued
316    Queued,
317    /// Command is executing
318    Executing,
319    /// Command completed successfully
320    Completed,
321    /// Command failed
322    Failed,
323    /// Command was cancelled
324    Cancelled,
325    /// Command timed out
326    TimedOut,
327}
328
329impl CommandExecutionProtocol {
330    /// Create a new command execution protocol
331    pub fn new(config: ProtocolConfig) -> Self {
332        Self {
333            config,
334            pending_commands: HashMap::new(),
335        }
336    }
337
338    /// Submit a command for execution
339    pub async fn submit_command(
340        &mut self,
341        command_type: &str,
342        target_device: &str,
343        parameters: HashMap<String, serde_json::Value>,
344    ) -> DeviceResult<String> {
345        let command_id = format!("cmd_{}", uuid::Uuid::new_v4());
346
347        let pending_command = PendingCommand {
348            command_id: command_id.clone(),
349            command_type: command_type.to_string(),
350            target_device: target_device.to_string(),
351            parameters,
352            submitted_at: SystemTime::now(),
353            expected_completion: None,
354            status: CommandStatus::Queued,
355        };
356
357        self.pending_commands
358            .insert(command_id.clone(), pending_command);
359        Ok(command_id)
360    }
361
362    /// Get command status
363    pub fn get_command_status(&self, command_id: &str) -> DeviceResult<CommandStatus> {
364        self.pending_commands
365            .get(command_id)
366            .map(|cmd| cmd.status.clone())
367            .ok_or_else(|| DeviceError::InvalidInput(format!("Command {command_id} not found")))
368    }
369
370    /// Cancel a command
371    pub async fn cancel_command(&mut self, command_id: &str) -> DeviceResult<()> {
372        if let Some(command) = self.pending_commands.get_mut(command_id) {
373            command.status = CommandStatus::Cancelled;
374            Ok(())
375        } else {
376            Err(DeviceError::InvalidInput(format!(
377                "Command {command_id} not found"
378            )))
379        }
380    }
381
382    /// Get all pending commands
383    pub fn get_pending_commands(&self) -> Vec<&PendingCommand> {
384        self.pending_commands.values().collect()
385    }
386}
387
388/// Status monitoring protocol
389pub struct StatusMonitoringProtocol {
390    config: ProtocolConfig,
391    monitored_devices: HashMap<String, DeviceMonitoringInfo>,
392}
393
394/// Device monitoring information
395#[derive(Debug, Clone, Serialize, Deserialize)]
396pub struct DeviceMonitoringInfo {
397    /// Device ID
398    pub device_id: String,
399    /// Last status update
400    pub last_update: SystemTime,
401    /// Current status
402    pub current_status: DeviceStatus,
403    /// Status history
404    pub status_history: Vec<StatusHistoryEntry>,
405    /// Performance metrics
406    pub metrics: HashMap<String, f64>,
407}
408
409/// Status history entry
410#[derive(Debug, Clone, Serialize, Deserialize)]
411pub struct StatusHistoryEntry {
412    /// Timestamp
413    pub timestamp: SystemTime,
414    /// Status
415    pub status: DeviceStatus,
416    /// Additional information
417    pub info: Option<String>,
418}
419
420impl StatusMonitoringProtocol {
421    /// Create a new status monitoring protocol
422    pub fn new(config: ProtocolConfig) -> Self {
423        Self {
424            config,
425            monitored_devices: HashMap::new(),
426        }
427    }
428
429    /// Start monitoring a device
430    pub fn start_monitoring(&mut self, device_id: &str) -> DeviceResult<()> {
431        let monitoring_info = DeviceMonitoringInfo {
432            device_id: device_id.to_string(),
433            last_update: SystemTime::now(),
434            current_status: DeviceStatus::Unknown,
435            status_history: Vec::new(),
436            metrics: HashMap::new(),
437        };
438
439        self.monitored_devices
440            .insert(device_id.to_string(), monitoring_info);
441        Ok(())
442    }
443
444    /// Stop monitoring a device
445    pub fn stop_monitoring(&mut self, device_id: &str) -> DeviceResult<()> {
446        self.monitored_devices.remove(device_id);
447        Ok(())
448    }
449
450    /// Update device status
451    pub fn update_device_status(
452        &mut self,
453        device_id: &str,
454        status: DeviceStatus,
455        info: Option<String>,
456    ) -> DeviceResult<()> {
457        if let Some(monitoring_info) = self.monitored_devices.get_mut(device_id) {
458            let history_entry = StatusHistoryEntry {
459                timestamp: SystemTime::now(),
460                status: status.clone(),
461                info,
462            };
463
464            monitoring_info.current_status = status;
465            monitoring_info.last_update = SystemTime::now();
466            monitoring_info.status_history.push(history_entry);
467
468            // Keep only recent history (last 1000 entries)
469            if monitoring_info.status_history.len() > 1000 {
470                monitoring_info.status_history.drain(0..500);
471            }
472
473            Ok(())
474        } else {
475            Err(DeviceError::DeviceNotFound(format!(
476                "Device {device_id} not found in monitoring list"
477            )))
478        }
479    }
480
481    /// Get device status
482    pub fn get_device_status(&self, device_id: &str) -> DeviceResult<&DeviceMonitoringInfo> {
483        self.monitored_devices.get(device_id).ok_or_else(|| {
484            DeviceError::DeviceNotFound(format!("Device {device_id} not found in monitoring list"))
485        })
486    }
487
488    /// Get all monitored devices
489    pub fn get_monitored_devices(&self) -> Vec<&DeviceMonitoringInfo> {
490        self.monitored_devices.values().collect()
491    }
492}
493
494impl Default for ProtocolConfig {
495    fn default() -> Self {
496        Self {
497            protocol_type: ProtocolType::Http,
498            connection_params: ConnectionParams::default(),
499            authentication: AuthenticationConfig::default(),
500            timeouts: TimeoutConfig::default(),
501            retry_config: RetryConfig::default(),
502        }
503    }
504}
505
506impl Default for ConnectionParams {
507    fn default() -> Self {
508        Self {
509            host: "localhost".to_string(),
510            port: 8080,
511            secure: false,
512            endpoint: "/api/v1".to_string(),
513            parameters: HashMap::new(),
514        }
515    }
516}
517
518impl Default for AuthenticationConfig {
519    fn default() -> Self {
520        Self {
521            auth_type: AuthenticationType::None,
522            username: None,
523            credentials: None,
524            api_key: None,
525            certificate_path: None,
526        }
527    }
528}
529
530impl Default for TimeoutConfig {
531    fn default() -> Self {
532        Self {
533            connection_timeout: Duration::from_secs(30),
534            request_timeout: Duration::from_secs(60),
535            response_timeout: Duration::from_secs(120),
536            keepalive_timeout: Duration::from_secs(300),
537        }
538    }
539}
540
541impl Default for RetryConfig {
542    fn default() -> Self {
543        Self {
544            max_retries: 3,
545            initial_delay: Duration::from_millis(100),
546            max_delay: Duration::from_secs(30),
547            backoff_multiplier: 2.0,
548            jitter_factor: 0.1,
549        }
550    }
551}
552
553/// Create a protocol message
554pub fn create_protocol_message(
555    message_type: MessageType,
556    sender: &str,
557    recipient: &str,
558    payload: HashMap<String, serde_json::Value>,
559    priority: MessagePriority,
560) -> ProtocolMessage {
561    ProtocolMessage {
562        message_id: uuid::Uuid::new_v4().to_string(),
563        message_type,
564        timestamp: SystemTime::now(),
565        sender: sender.to_string(),
566        recipient: recipient.to_string(),
567        payload,
568        priority,
569    }
570}
571
572/// Create a protocol response
573pub fn create_protocol_response(
574    request_id: &str,
575    success: bool,
576    status_code: u16,
577    status_message: &str,
578    data: HashMap<String, serde_json::Value>,
579    execution_time: Duration,
580) -> ProtocolResponse {
581    ProtocolResponse {
582        response_id: request_id.to_string(),
583        timestamp: SystemTime::now(),
584        success,
585        status_code,
586        status_message: status_message.to_string(),
587        data,
588        execution_time,
589    }
590}
591
592#[cfg(test)]
593mod tests {
594    use super::*;
595
596    #[test]
597    fn test_protocol_config_creation() {
598        let config = ProtocolConfig::default();
599        assert_eq!(config.protocol_type, ProtocolType::Http);
600        assert_eq!(config.connection_params.host, "localhost");
601        assert_eq!(config.connection_params.port, 8080);
602    }
603
604    #[test]
605    fn test_protocol_message_creation() {
606        let payload = HashMap::new();
607        let message = create_protocol_message(
608            MessageType::Status,
609            "client",
610            "device_1",
611            payload,
612            MessagePriority::Normal,
613        );
614
615        assert_eq!(message.message_type, MessageType::Status);
616        assert_eq!(message.sender, "client");
617        assert_eq!(message.recipient, "device_1");
618        assert_eq!(message.priority, MessagePriority::Normal);
619    }
620
621    #[test]
622    fn test_device_discovery() {
623        let config = ProtocolConfig::default();
624        let discovery = DeviceDiscoveryProtocol::new(config);
625        assert_eq!(discovery.get_discovered_devices().len(), 0);
626    }
627}
628
629// Add uuid dependency if not already present
630mod uuid {
631    use std::fmt;
632
633    pub struct Uuid([u8; 16]);
634
635    impl Uuid {
636        pub fn new_v4() -> Self {
637            // Simple mock implementation - in real code would use proper UUID generation
638            use std::collections::hash_map::DefaultHasher;
639            use std::hash::{Hash, Hasher};
640            use std::time::SystemTime;
641
642            let mut hasher = DefaultHasher::new();
643            SystemTime::now().hash(&mut hasher);
644            let hash = hasher.finish();
645
646            let mut bytes = [0u8; 16];
647            bytes[0..8].copy_from_slice(&hash.to_le_bytes());
648            bytes[8..16].copy_from_slice(&hash.to_be_bytes());
649
650            Self(bytes)
651        }
652    }
653
654    impl fmt::Display for Uuid {
655        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
656            write!(f, "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
657                self.0[0], self.0[1], self.0[2], self.0[3],
658                self.0[4], self.0[5],
659                self.0[6], self.0[7],
660                self.0[8], self.0[9],
661                self.0[10], self.0[11], self.0[12], self.0[13], self.0[14], self.0[15])
662        }
663    }
664}