104 lines
3.2 KiB
Rust
104 lines
3.2 KiB
Rust
//! [TSM.ID].[11031972] -- Platform X Ecosystem
|
|
//! xcu-omni-relay -- Omni-directional relay routing bridge
|
|
#![deny(warnings)]
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
use std::collections::HashMap;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
#[derive(Debug)]
|
|
pub enum BridgeError {
|
|
ConnectionFailed(String),
|
|
ConfigError(String),
|
|
OperationFailed(String),
|
|
NotReady,
|
|
}
|
|
|
|
impl std::fmt::Display for BridgeError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::ConnectionFailed(e) => write!(f, "Connection failed: {e}"),
|
|
Self::ConfigError(e) => write!(f, "Config error: {e}"),
|
|
Self::OperationFailed(e) => write!(f, "Op failed: {e}"),
|
|
Self::NotReady => write!(f, "Not ready"),
|
|
}
|
|
}
|
|
}
|
|
impl std::error::Error for BridgeError {}
|
|
pub type Result<T> = std::result::Result<T, BridgeError>;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct BridgeConfig {
|
|
pub name: String,
|
|
pub endpoint: String,
|
|
pub params: HashMap<String, String>,
|
|
pub enabled: bool,
|
|
}
|
|
|
|
impl BridgeConfig {
|
|
pub fn new(name: &str, endpoint: &str) -> Self {
|
|
Self { name: name.to_string(), endpoint: endpoint.to_string(), params: HashMap::new(), enabled: true }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum BridgeState { Disconnected, Connecting, Connected, Error(String) }
|
|
|
|
pub struct Bridge {
|
|
config: BridgeConfig,
|
|
state: Arc<Mutex<BridgeState>>,
|
|
message_count: Arc<Mutex<u64>>,
|
|
}
|
|
|
|
impl Bridge {
|
|
pub fn new(config: BridgeConfig) -> Result<Self> {
|
|
Ok(Self {
|
|
config, state: Arc::new(Mutex::new(BridgeState::Disconnected)),
|
|
message_count: Arc::new(Mutex::new(0)),
|
|
})
|
|
}
|
|
|
|
pub fn connect(&self) -> Result<()> {
|
|
let mut s = self.state.lock().map_err(|e| BridgeError::OperationFailed(e.to_string()))?;
|
|
*s = BridgeState::Connecting;
|
|
*s = BridgeState::Connected;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn disconnect(&self) -> Result<()> {
|
|
let mut s = self.state.lock().map_err(|e| BridgeError::OperationFailed(e.to_string()))?;
|
|
*s = BridgeState::Disconnected;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn send(&self, _payload: &[u8]) -> Result<u64> {
|
|
let s = self.state.lock().map_err(|e| BridgeError::OperationFailed(e.to_string()))?;
|
|
if *s != BridgeState::Connected { return Err(BridgeError::NotReady); }
|
|
drop(s);
|
|
let mut c = self.message_count.lock().map_err(|e| BridgeError::OperationFailed(e.to_string()))?;
|
|
*c += 1;
|
|
Ok(*c)
|
|
}
|
|
|
|
pub fn state(&self) -> Result<BridgeState> {
|
|
Ok(self.state.lock().map_err(|e| BridgeError::OperationFailed(e.to_string()))?.clone())
|
|
}
|
|
|
|
pub fn config(&self) -> &BridgeConfig { &self.config }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
#[test]
|
|
fn test_bridge() {
|
|
let b = Bridge::new(BridgeConfig::new("xcu-omni-relay", "localhost:3000")).unwrap();
|
|
assert_eq!(b.state().unwrap(), BridgeState::Disconnected);
|
|
b.connect().unwrap();
|
|
assert_eq!(b.state().unwrap(), BridgeState::Connected);
|
|
b.send(b"hello").unwrap();
|
|
b.disconnect().unwrap();
|
|
assert_eq!(b.state().unwrap(), BridgeState::Disconnected);
|
|
}
|
|
}
|