use std::sync::{Arc, RwLock};
use std::fmt::Debug;
use async_trait::async_trait;
use crate::dev::{AttrInfo, AttrRead, AttrValueEvent, AttrWrite, CommandInfo, DevProxy, DevState};
use crate::error::Result;
use crate::data::Data;
#[async_trait]
pub trait Backend: Debug + Send + Sync {
async fn connect_device(&self, itr: &str) -> Result<Arc<dyn DevBackend>>;
async fn connect_device_at(&self, name: &str, host: &str, port: u16) -> Result<Arc<dyn DevBackend>>;
async fn connect_database(&self, host: &str, port: u16) -> Result<Arc<dyn DevBackend>>;
async fn bind_device(&self, dev: Arc<dyn DevBackend>) -> Result<()>;
}
#[async_trait]
pub trait DevBackend: Debug + Send + Sync {
async fn name(&self) -> Result<Arc<str>>;
async fn admin_dev_name(&self) -> Result<Arc<str>>;
async fn description(&self) -> Result<Arc<str>>;
async fn ping(&self) -> Result<()>;
async fn state(&self) -> Result<DevState>;
async fn status(&self) -> Result<String>;
async fn black_box(&self, max: Option<usize>) -> Result<Vec<String>>;
async fn command(&self, name: &str, data: Data<'_>) -> Result<Box<dyn DevCommandBackend>>;
async fn read_attr(&self, names: Option<&[&str]>) -> Result<Box<dyn DevReadAttrBackend>>;
async fn write_attr(&self, attrs: &[AttrWrite<'_, Data<'_>>]) -> Result<Box<dyn DevWriteAttrBackend>>;
async fn get_command_info(&self, names: Option<&[&str]>) -> Result<Box<dyn DevGetCommandInfoBackend>>;
async fn get_attr_info(&self, names: Option<&[&str]>) -> Result<Box<dyn DevGetAttrInfoBackend>>;
}
pub trait DevCommandBackend: Debug + Send {
fn get(&self) -> Result<Data<'_>>;
}
pub trait DevReadAttrBackend: Debug + Send {
fn len(&self) -> usize;
fn get(&self, index: usize) -> Result<AttrRead<'_, Data<'_>>>;
}
pub trait DevWriteAttrBackend: Debug + Send {
fn len(&self) -> usize;
fn check(&self, index: usize) -> Result<()>;
}
pub trait DevGetCommandInfoBackend: Debug + Send {
fn len(&self) -> usize;
fn get(&self, index: usize) -> Result<CommandInfo<'_>>;
}
pub trait DevGetAttrInfoBackend: Debug + Send {
fn len(&self) -> usize;
fn get(&self, index: usize) -> Result<AttrInfo<'_>>;
}
static BACKENDS: RwLock<Option<Arc<[Arc<dyn Backend>]>>> = RwLock::new(None);
pub fn register_backend(backend: Arc<dyn Backend>) {
let mut guard = BACKENDS.write().unwrap();
let backends = guard.as_deref().unwrap_or(&[]);
let backends = backends.iter()
.cloned()
.chain(Some(backend))
.collect::<Vec<_>>();
*guard = Some(Arc::from(backends))
}
pub fn read_backends() -> Option<Arc<[Arc<dyn Backend>]>> {
BACKENDS.read().unwrap().clone()
}
#[async_trait]
pub trait EventBackend: Debug + Send + Sync {
async fn subscribe_attr_value(&self, dev: &DevProxy, name: &str, event: AttrValueEvent) -> Result<Box<dyn AttrValueChannelBackend>>;
async fn subscribe_attr_ready(&self, dev: &DevProxy, name: &str) -> Result<Box<dyn AttrReadyChannelBackend>>;
async fn subscribe_attr_conf(&self, dev: &DevProxy, name: &str) -> Result<Box<dyn AttrConfChannelBackend>>;
}
#[async_trait]
pub trait AttrValueChannelBackend: Debug + Send {
async fn wait(&mut self) -> Result<Box<dyn AttrValueChannelGuard + '_>>;
}
pub trait AttrValueChannelGuard: Debug {
fn get(&self) -> Result<AttrRead<'_, Data<'_>>>;
}
#[async_trait]
pub trait AttrReadyChannelBackend: Debug + Send {
async fn wait(&mut self) -> Result<()>;
}
#[async_trait]
pub trait AttrConfChannelBackend: Debug + Send {
async fn wait(&mut self) -> Result<()>;
}
static EVENT_BACKENDS: RwLock<Option<Arc<[Arc<dyn EventBackend>]>>> = RwLock::new(None);
pub fn register_event_backend(backend: Arc<dyn EventBackend>) {
let mut guard = EVENT_BACKENDS.write().unwrap();
let backends = guard.as_deref().unwrap_or(&[]);
let backends = backends.iter()
.cloned()
.chain(Some(backend))
.collect::<Vec<_>>();
*guard = Some(Arc::from(backends))
}
pub fn read_event_backends() -> Option<Arc<[Arc<dyn EventBackend>]>> {
EVENT_BACKENDS.read().unwrap().clone()
}