mod runtime_queue;
mod runtime;
mod convert;
mod command;
pub(crate) mod attr;
use std::collections::HashSet;
use std::ffi::{CStr, CString};
use std::hash::{Hash, Hasher};
use std::fmt::{self, Debug};
use std::sync::{Arc, Weak};
use std::time::Duration;
use std::borrow::Borrow;
use tokio::sync::{Mutex, OnceCell};
use tokio::runtime as rt;
use async_trait::async_trait;
use tracing::trace;
use tango_omniorb as orb;
use crate::backend::{self, Backend, DevBackend, DevCommandBackend, DevGetAttrInfoBackend, DevGetCommandInfoBackend, DevReadAttrBackend, DevWriteAttrBackend};
use crate::omniorb::command::DevGetCommandInfoBackendExt;
use crate::dev::{AttrWrite, DevState};
use crate::error::{Error, ErrorKind, Result};
use crate::data::Data;
use attr::{DevReadAttrFromValueList, DevWriteAttrFromMultiDevFailed, DevWriteAttrOk, DevGetAttrConfigFromList,
attr_write_to_value_v1, attr_write_to_value_v4};
use command::{DevCommandFromAny, DevGetCommandInfoMany, DevGetCommandInfoSingle,
command_data_to_any};
use runtime::AsyncOrb;
const ALL_ATTRIBUTES: &'static str = "All attributes";
const ALL_ATTRIBUTES_3: &'static str = "All attributes_3";
pub struct CorbaBackend {
this: Weak<Self>,
orb: AsyncOrb,
servants: Mutex<HashSet<CorbaDevServant>>,
}
impl CorbaBackend {
pub fn init() -> Result<Arc<Self>> {
let orb = AsyncOrb::init()?;
Ok(Arc::new_cyclic(|this| {
Self {
this: this.clone(),
orb,
servants: Mutex::new(HashSet::new())
}
}))
}
#[inline]
pub fn register(self: Arc<Self>) {
backend::register_backend(self);
}
#[allow(unused)]
#[inline]
fn this(&self) -> Arc<Self> {
self.this.upgrade().unwrap()
}
async fn connect_device_inner(&self, corba_name: String) -> Result<Arc<dyn DevBackend>> {
trace!(?corba_name, "Connecting to device");
orb::set_client_connect_timeout(Duration::from_millis(3000));
orb::set_client_call_timeout(Duration::from_millis(3000));
let res = self.orb.dispatch(move |orb| {
let obj = orb.string_to_object(&corba_name)?;
if let Some(v6) = orb::Tango_Device_6::narrow(&obj)? {
v6.non_existent()?;
Ok(Some(OrbDev::from_v6(v6)))
} else if let Some(v5) = orb::Tango_Device_5::narrow(&obj)? {
v5.non_existent()?;
Ok(Some(OrbDev::from_v5(v5)))
} else if let Some(v4) = orb::Tango_Device_4::narrow(&obj)? {
v4.non_existent()?;
Ok(Some(OrbDev::from_v4(v4)))
} else if let Some(v3) = orb::Tango_Device_3::narrow(&obj)? {
v3.non_existent()?;
Ok(Some(OrbDev::from_v3(v3)))
} else if let Some(v2) = orb::Tango_Device_2::narrow(&obj)? {
v2.non_existent()?;
Ok(Some(OrbDev::from_v2(v2)))
} else if let Some(v1) = orb::Tango_Device::narrow(&obj)? {
v1.non_existent()?;
Ok(Some(OrbDev::from_v1(v1)))
} else {
Ok(None)
}
}).await;
let obj = match res {
Ok(Some(obj)) => obj,
Ok(None) => return Err(Error::new(ErrorKind::DevNotConnected)),
Err(e) if e.kind() == ErrorKind::TimedOut => return Err(Error::new(ErrorKind::ServerNotConnected)),
Err(e) => return Err(e),
};
obj.v1().set_client_call_timeout(Duration::from_hours(24 * 365));
Ok(CorbaDevBackend::new(self.orb.clone(), obj))
}
}
#[async_trait]
impl Backend for CorbaBackend {
async fn connect_device(&self, itr: &str) -> Result<Arc<dyn DevBackend>> {
if !itr.starts_with("corbaloc:") && !itr.starts_with("corbaname:") && !itr.starts_with("IOR:") {
return Err(Error::new(ErrorKind::NotHandled));
}
let itr = itr.to_string();
self.connect_device_inner(itr).await
}
async fn connect_device_at(&self, name: &str, host: &str, port: u16) -> Result<Arc<dyn DevBackend>> {
let itr = format!("corbaloc:iiop:{host}:{port}/{name}");
self.connect_device_inner(itr).await
}
async fn connect_database(&self, host: &str, port: u16) -> Result<Arc<dyn DevBackend>> {
self.connect_device_at("database", host, port).await
}
async fn bind_device(&self, backend: Arc<dyn DevBackend>) -> Result<()> {
let name = backend.name().await
.map_err(|e| Error::new(ErrorKind::Internal)
.with_description(format!("Could not get the name of the device to bind"))
.with_parent(e))?;
let adapter = CorbaDevAdapter {
runtime: rt::Handle::current(),
backend: Arc::clone(&backend),
};
let servant = adapter.instantiate();
let servant = self.orb.dispatch(move |orb| {
let poa = orb.resolve_initial_references("RootPOA")?;
let poa = orb::PortableServer_POA::narrow(&poa)?
.ok_or_else(|| Error::new(ErrorKind::Internal)
.with_description("Cannot narrow RootPOA to PortableServer::POA type"))?;
let object_id = poa.activate_object(&servant)?;
Ok(CorbaDevServant {
name,
backend,
servant,
object_id,
})
}).await?;
let mut servants = self.servants.lock().await;
servants.insert(servant);
Ok(())
}
}
impl Debug for CorbaBackend {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CorbaBackend")
.finish()
}
}
struct CorbaDevBackend {
this: Weak<Self>,
tango_ident: orb::Tango_ClntIdent,
orb: AsyncOrb,
obj: OrbDev,
name: OnceCell<Arc<str>>,
admin_name: OnceCell<Arc<str>>,
}
impl CorbaDevBackend {
fn new(orb: AsyncOrb, obj: OrbDev) -> Arc<Self> {
Arc::new_cyclic(|this| {
Self {
this: this.clone(),
tango_ident: orb::Tango_ClntIdent::with_java_clnt(orb::CppBox::new(orb::Tango_JavaClntIdent {
MainClass: "RustTango".try_into().unwrap(),
uuid: [0; 2],
})),
orb,
obj,
name: OnceCell::new(),
admin_name: OnceCell::new(),
}
})
}
#[inline]
fn this(&self) -> Arc<Self> {
self.this.upgrade().unwrap()
}
}
impl Debug for CorbaDevBackend {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CorbaDevBackend")
.finish()
}
}
#[async_trait]
impl DevBackend for CorbaDevBackend {
async fn name(&self) -> Result<Arc<str>> {
self.name.get_or_try_init(async || {
let this = self.this();
self.orb.dispatch(move |_| this.obj.v1()
.name()
.map_err(Error::from)
.map(|s| Arc::from(s.to_string_lossy())))
.await
}).await.map(Arc::clone)
}
async fn admin_dev_name(&self) -> Result<Arc<str>> {
self.admin_name.get_or_try_init(async || {
let this = self.this();
self.orb.dispatch(move |_| this.obj.v1()
.adm_name()
.map_err(Error::from)
.map(|s| Arc::from(s.to_string_lossy())))
.await
}).await.map(Arc::clone)
}
async fn description(&self) -> Result<Arc<str>> {
let this = self.this();
self.orb.dispatch(move |_| this.obj.v1()
.description()
.map_err(Error::from)
.map(|s| Arc::from(s.to_string_lossy())))
.await
}
async fn ping(&self) -> Result<()> {
let this = self.this();
self.orb.dispatch(move |_| this.obj.v1()
.ping()
.map_err(Error::from))
.await
}
async fn state(&self) -> Result<DevState> {
let this = self.this();
self.orb.dispatch(move |_| this.obj.v1()
.state()
.map(orb::Tango_DevState::into)
.map_err(Error::from))
.await
}
async fn status(&self) -> Result<String> {
let this = self.this();
self.orb.dispatch(move |_| this.obj.v1()
.status()
.map(|s| s.to_string_lossy().into_owned())
.map_err(Error::from))
.await
}
async fn black_box(&self, max: Option<usize>) -> Result<Vec<String>> {
let this = self.this();
self.orb.dispatch(move |_| {
let res = this.obj.v1().black_box(max.and_then(|max| i32::try_from(max).ok()).unwrap_or(orb::CORBA_Long::MAX))?;
let ret = res.into_inner()
.into_iter()
.map(|s| s.as_cstr().to_string_lossy().into_owned())
.collect::<Vec<_>>();
Ok(ret)
}).await
}
async fn command(&self, name: &str, data: Data<'_>) -> Result<Box<dyn DevCommandBackend>> {
let Ok(name) = CString::new(name) else {
return Err(Error::new(ErrorKind::CommandNameInvalid)
.with_append_description(format_args!("{name:?}")));
};
let any_in = match command_data_to_any(data) {
Ok(any) => any,
Err(e) => return Err(e),
};
let this = self.this();
self.orb.dispatch(move |_| {
let any_out = match &this.obj {
OrbDev::V1 { v1, .. } =>
v1.command_inout(&name, &any_in),
OrbDev::V2 { v2, .. } |
OrbDev::V3 { v2, .. } =>
v2.command_inout_2(&name, &any_in, orb::Tango_DevSource::CACHE_DEV),
OrbDev::V4 { v4, .. } |
OrbDev::V5 { v4, .. } |
OrbDev::V6 { v4, .. } =>
v4.command_inout_4(&name, &any_in, orb::Tango_DevSource::CACHE_DEV, &this.tango_ident),
}?.into_inner();
let ret: Box<dyn DevCommandBackend> = Box::new(DevCommandFromAny::new(any_out));
Ok(ret)
}).await
}
async fn read_attr(&self, names: Option<&[&str]>) -> Result<Box<dyn DevReadAttrBackend>> {
const ALL: &[&str] = &[ALL_ATTRIBUTES];
let names = match names {
Some(names) => {
if names.contains(&ALL_ATTRIBUTES) || names.contains(&ALL_ATTRIBUTES_3) {
return Err(Error::new(ErrorKind::AttrNameInvalid)
.with_append_description("Given attribute names contains the 'all attributes' marker")
.with_append_description(format_args!("{names:?}")));
}
names
}
None => ALL,
};
let mut names_arr = orb::Tango_DevVarStringArray(orb::CORBA_Sequence::with_capacity(names.len()));
for &name in names {
let Ok(name) = orb::CORBA_String::try_from(name) else {
return Err(Error::new(ErrorKind::AttrNameInvalid)
.with_append_description(format_args!("{name:?}")));
};
names_arr.push(name);
}
let this = self.this();
self.orb.dispatch(move |_| {
let ret: Box<dyn DevReadAttrBackend> = match &this.obj {
OrbDev::V1 { v1, .. } |
OrbDev::V2 { v1, .. } =>
Box::new(DevReadAttrFromValueList::new(v1.read_attributes(&names_arr)?)),
OrbDev::V3 { v3, .. } =>
Box::new(DevReadAttrFromValueList::new(v3.read_attributes_3(&names_arr, orb::Tango_DevSource::CACHE_DEV)?)),
OrbDev::V4 { v4, .. } =>
Box::new(DevReadAttrFromValueList::new(v4.read_attributes_4(&names_arr, orb::Tango_DevSource::CACHE_DEV, &this.tango_ident)?)),
OrbDev::V5 { v5, .. } |
OrbDev::V6 { v5, .. } =>
Box::new(DevReadAttrFromValueList::new(v5.read_attributes_5(&names_arr, orb::Tango_DevSource::CACHE_DEV, &this.tango_ident)?))
};
Ok(ret)
}).await
}
async fn write_attr(&self, attrs: &[AttrWrite<'_, Data<'_>>]) -> Result<Box<dyn DevWriteAttrBackend>> {
#[derive(Debug)]
enum AttributeValueList {
V1(orb::Tango_AttributeValueList),
V4(orb::Tango_AttributeValueList_4),
}
impl AttributeValueList {
fn v1(&self) -> &orb::Tango_AttributeValueList {
match self {
Self::V1(list) => list,
_ => panic!()
}
}
fn v4(&self) -> &orb::Tango_AttributeValueList_4 {
match self {
Self::V4(list) => list,
_ => panic!()
}
}
}
let len = attrs.len();
let value_list = if self.obj.v4().is_some() {
let mut val_list = orb::Tango_AttributeValueList_4(orb::CORBA_Sequence::with_capacity(attrs.len()));
for attr in attrs {
match attr_write_to_value_v4(attr) {
Ok(val) => val_list.push(val),
Err(e) => return Err(e),
}
}
AttributeValueList::V4(val_list)
} else {
let mut val_list = orb::Tango_AttributeValueList(orb::CORBA_Sequence::with_capacity(attrs.len()));
for attr in attrs {
match attr_write_to_value_v1(attr) {
Ok(val) => val_list.push(val),
Err(e) => return Err(e),
}
}
AttributeValueList::V1(val_list)
};
let this = self.this();
self.orb.dispatch(move |_| {
let res = match &this.obj {
OrbDev::V1 { v1, .. } |
OrbDev::V2 { v1, .. } =>
v1.write_attributes(value_list.v1()),
OrbDev::V3 { v3, .. } =>
v3.write_attributes_3(value_list.v1()),
OrbDev::V4 { v4, .. } |
OrbDev::V5 { v4, .. } |
OrbDev::V6 { v4, .. } =>
v4.write_attributes_4(value_list.v4(), &this.tango_ident),
};
let err = match res {
Ok(()) => return Ok(Box::new(DevWriteAttrOk { len }) as Box<dyn DevWriteAttrBackend>),
Err(e) => e,
};
let err = match orb::Tango_MultiDevFailed::downcast(err) {
Ok(err) => return Ok(Box::new(DevWriteAttrFromMultiDevFailed { len, err }) as Box<dyn DevWriteAttrBackend>),
Err(err) => err,
};
Err(err.into())
}).await
}
async fn get_command_info(&self, names: Option<&[&str]>) -> Result<Box<dyn DevGetCommandInfoBackend>> {
if let Some(&[name]) = names {
let Ok(name) = orb::CORBA_String::try_from(name) else {
return Err(Error::new(ErrorKind::CommandNameInvalid)
.with_append_description(format_args!("{name:?}")));
};
let this = self.this();
self.orb.dispatch(move |_| {
let ret: Box<dyn DevGetCommandInfoBackend> = match &this.obj {
OrbDev::V1 { v1, .. } =>
Box::new(DevGetCommandInfoSingle::new(v1.command_query(&name)?)),
OrbDev::V2 { v2, .. } |
OrbDev::V3 { v2, .. } |
OrbDev::V4 { v2, .. } |
OrbDev::V5 { v2, .. } |
OrbDev::V6 { v2, .. } =>
Box::new(DevGetCommandInfoSingle::new(v2.command_query_2(&name)?)),
};
Ok(ret)
}).await
} else {
let this = self.this();
let mut ret = self.orb.dispatch(move |_| {
let ret: Box<dyn DevGetCommandInfoBackendExt> = match &this.obj {
OrbDev::V1 { v1, .. } =>
Box::new(DevGetCommandInfoMany::new(v1.command_list_query()?)),
OrbDev::V2 { v2, .. } |
OrbDev::V3 { v2, .. } |
OrbDev::V4 { v2, .. } |
OrbDev::V5 { v2, .. } |
OrbDev::V6 { v2, .. } =>
Box::new(DevGetCommandInfoMany::new(v2.command_list_query_2()?)),
};
Ok(ret)
}).await?;
if let Some(names) = names {
ret.init_mapping(names);
}
Ok(ret)
}
}
async fn get_attr_info(&self, names: Option<&[&str]>) -> Result<Box<dyn DevGetAttrInfoBackend>> {
const ALL: &[&str] = &[ALL_ATTRIBUTES];
const ALL_3: &[&str] = &[ALL_ATTRIBUTES_3];
let names = match names {
Some(names) => {
if names.contains(&ALL_ATTRIBUTES) || names.contains(&ALL_ATTRIBUTES_3) {
return Err(Error::new(ErrorKind::AttrNameInvalid)
.with_append_description("Given attribute names contains the 'all attributes' marker")
.with_append_description(format_args!("{names:?}")));
}
names
}
None => {
if self.obj.v3().is_some() {
ALL_3
} else {
ALL
}
}
};
let mut names_arr = orb::Tango_DevVarStringArray(orb::CORBA_Sequence::with_capacity(names.len()));
for &name in names {
let Ok(name) = orb::CORBA_String::try_from(name) else {
return Err(Error::new(ErrorKind::AttrNameInvalid)
.with_append_description(format_args!("{name:?}")));
};
names_arr.push(name);
}
let this = self.this();
self.orb.dispatch(move |_| {
let ret: Box<dyn DevGetAttrInfoBackend> = match &this.obj {
OrbDev::V1 { v1, .. } =>
Box::new(DevGetAttrConfigFromList::new(v1.get_attribute_config(&names_arr)?)),
OrbDev::V2 { v2, .. } =>
Box::new(DevGetAttrConfigFromList::new(v2.get_attribute_config_2(&names_arr)?)),
OrbDev::V3 { v3, .. } |
OrbDev::V4 { v3, .. } =>
Box::new(DevGetAttrConfigFromList::new(v3.get_attribute_config_3(&names_arr)?)),
OrbDev::V5 { v5, .. } |
OrbDev::V6 { v5, .. } =>
Box::new(DevGetAttrConfigFromList::new(v5.get_attribute_config_5(&names_arr)?)),
};
Ok(ret)
}).await
}
}
#[allow(unused)]
enum OrbDev {
V1 {
v1: orb::Tango_Device,
},
V2 {
v1: orb::Tango_Device,
v2: orb::Tango_Device_2,
},
V3 {
v1: orb::Tango_Device,
v2: orb::Tango_Device_2,
v3: orb::Tango_Device_3,
},
V4 {
v1: orb::Tango_Device,
v2: orb::Tango_Device_2,
v3: orb::Tango_Device_3,
v4: orb::Tango_Device_4,
},
V5 {
v1: orb::Tango_Device,
v2: orb::Tango_Device_2,
v3: orb::Tango_Device_3,
v4: orb::Tango_Device_4,
v5: orb::Tango_Device_5,
},
V6 {
v1: orb::Tango_Device,
v2: orb::Tango_Device_2,
v3: orb::Tango_Device_3,
v4: orb::Tango_Device_4,
v5: orb::Tango_Device_5,
v6: orb::Tango_Device_6,
},
}
#[allow(unused)]
impl OrbDev {
pub fn from_v1(v1: orb::Tango_Device) -> Self {
Self::V1 { v1 }
}
pub fn from_v2(v2: orb::Tango_Device_2) -> Self {
let v1 = v2.parent().duplicate();
Self::V2 { v1, v2 }
}
pub fn from_v3(v3: orb::Tango_Device_3) -> Self {
let v2 = v3.parent().duplicate();
let v1 = v2.parent().duplicate();
Self::V3 { v1, v2, v3 }
}
pub fn from_v4(v4: orb::Tango_Device_4) -> Self {
let v3 = v4.parent().duplicate();
let v2 = v3.parent().duplicate();
let v1 = v2.parent().duplicate();
Self::V4 { v1, v2, v3, v4 }
}
pub fn from_v5(v5: orb::Tango_Device_5) -> Self {
let v4 = v5.parent().duplicate();
let v3 = v4.parent().duplicate();
let v2 = v3.parent().duplicate();
let v1 = v2.parent().duplicate();
Self::V5 { v1, v2, v3, v4, v5 }
}
pub fn from_v6(v6: orb::Tango_Device_6) -> Self {
let v5 = v6.parent().duplicate();
let v4 = v5.parent().duplicate();
let v3 = v4.parent().duplicate();
let v2 = v3.parent().duplicate();
let v1 = v2.parent().duplicate();
Self::V6 { v1, v2, v3, v4, v5, v6 }
}
#[inline]
pub fn v1(&self) -> &orb::Tango_Device {
match self {
OrbDev::V1 { v1, .. } => v1,
OrbDev::V2 { v1, .. } => v1,
OrbDev::V3 { v1, .. } => v1,
OrbDev::V4 { v1, .. } => v1,
OrbDev::V5 { v1, .. } => v1,
OrbDev::V6 { v1, .. } => v1,
}
}
#[inline]
pub fn v2(&self) -> Option<&orb::Tango_Device_2> {
Some(match self {
OrbDev::V1 { .. } => return None,
OrbDev::V2 { v2, .. } => v2,
OrbDev::V3 { v2, .. } => v2,
OrbDev::V4 { v2, .. } => v2,
OrbDev::V5 { v2, .. } => v2,
OrbDev::V6 { v2, .. } => v2,
})
}
#[inline]
pub fn v3(&self) -> Option<&orb::Tango_Device_3> {
Some(match self {
OrbDev::V1 { .. } => return None,
OrbDev::V2 { .. } => return None,
OrbDev::V3 { v3, .. } => v3,
OrbDev::V4 { v3, .. } => v3,
OrbDev::V5 { v3, .. } => v3,
OrbDev::V6 { v3, .. } => v3,
})
}
#[inline]
pub fn v4(&self) -> Option<&orb::Tango_Device_4> {
Some(match self {
OrbDev::V1 { .. } => return None,
OrbDev::V2 { .. } => return None,
OrbDev::V3 { .. } => return None,
OrbDev::V4 { v4, .. } => v4,
OrbDev::V5 { v4, .. } => v4,
OrbDev::V6 { v4, .. } => v4,
})
}
#[inline]
pub fn v5(&self) -> Option<&orb::Tango_Device_5> {
Some(match self {
OrbDev::V1 { .. } => return None,
OrbDev::V2 { .. } => return None,
OrbDev::V3 { .. } => return None,
OrbDev::V4 { .. } => return None,
OrbDev::V5 { v5, .. } => v5,
OrbDev::V6 { v5, .. } => v5,
})
}
pub fn v6(&self) -> Option<&orb::Tango_Device_6> {
Some(match self {
OrbDev::V1 { .. } => return None,
OrbDev::V2 { .. } => return None,
OrbDev::V3 { .. } => return None,
OrbDev::V4 { .. } => return None,
OrbDev::V5 { .. } => return None,
OrbDev::V6 { v6, .. } => v6,
})
}
}
impl fmt::Debug for OrbDev {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::V1 { v1, .. } => f.debug_tuple("V1").field(v1).finish(),
Self::V2 { v2, .. } => f.debug_tuple("V2").field(v2).finish(),
Self::V3 { v3, .. } => f.debug_tuple("V3").field(v3).finish(),
Self::V4 { v4, .. } => f.debug_tuple("V4").field(v4).finish(),
Self::V5 { v5, .. } => f.debug_tuple("V5").field(v5).finish(),
Self::V6 { v6, .. } => f.debug_tuple("V6").field(v6).finish(),
}
}
}
#[derive(Debug)]
struct CorbaDevServant {
name: Arc<str>,
backend: Arc<dyn DevBackend>,
servant: orb::PortableServer_Servant,
object_id: orb::PortableServer_ObjectId,
}
impl Borrow<str> for CorbaDevServant {
fn borrow(&self) -> &str {
&self.name
}
}
impl Eq for CorbaDevServant {}
impl PartialEq for CorbaDevServant {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Hash for CorbaDevServant {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
struct CorbaDevAdapter {
runtime: rt::Handle,
backend: Arc<dyn DevBackend>,
}
impl CorbaDevAdapter {
const DEF: orb::Tango_Device_AdapterDef<Self> = orb::Tango_Device_AdapterDef::<Self>::new();
pub fn instantiate(self) -> orb::PortableServer_Servant {
Self::DEF.instantiate(Box::new(self))
}
}
impl orb::CORBA_Object_Adapter for CorbaDevAdapter {}
impl orb::Tango_Device_Adapter for CorbaDevAdapter {
fn name(&self) -> std::result::Result<orb::CORBA_String, orb::CORBA_Exception> {
todo!()
}
fn description(&self) -> std::result::Result<orb::CORBA_String, orb::CORBA_Exception> {
todo!()
}
fn state(&self) -> std::result::Result<orb::Tango_DevState, orb::CORBA_Exception> {
todo!()
}
fn status(&self) -> std::result::Result<orb::CORBA_String, orb::CORBA_Exception> {
todo!()
}
fn adm_name(&self) -> std::result::Result<orb::CORBA_String, orb::CORBA_Exception> {
todo!()
}
fn command_inout(&self, command: &CStr, argin: &orb::CORBA_Any) -> std::result::Result<orb::CppBox<orb::CORBA_Any>, orb::CORBA_Exception> {
todo!()
}
fn get_attribute_config(&self, names: &orb::Tango_DevVarStringArray) -> std::result::Result<orb::CppBox<orb::Tango_AttributeConfigList>, orb::CORBA_Exception> {
todo!()
}
fn set_attribute_config(&self, new_conf: &orb::Tango_AttributeConfigList) -> std::result::Result<(), orb::CORBA_Exception> {
todo!()
}
fn read_attributes(&self, names: &orb::Tango_DevVarStringArray) -> std::result::Result<orb::CppBox<orb::Tango_AttributeValueList>, orb::CORBA_Exception> {
todo!()
}
fn write_attributes(&self, values: &orb::Tango_AttributeValueList) -> std::result::Result<(), orb::CORBA_Exception> {
todo!()
}
fn ping(&self) -> std::result::Result<(), orb::CORBA_Exception> {
todo!()
}
fn black_box(&self, n: orb::CORBA_Long) -> std::result::Result<orb::CppBox<orb::Tango_DevVarStringArray>, orb::CORBA_Exception> {
todo!()
}
fn info(&self) -> std::result::Result<orb::CppBox<orb::Tango_DevInfo>, orb::CORBA_Exception> {
todo!()
}
fn command_list_query(&self) -> std::result::Result<orb::CppBox<orb::Tango_DevCmdInfoList>, orb::CORBA_Exception> {
todo!()
}
fn command_query(&self, command: &CStr) -> std::result::Result<orb::CppBox<orb::Tango_DevCmdInfo>, orb::CORBA_Exception> {
todo!()
}
}