rstango 0.3.0

Implementation of the Tango distributed control system
Documentation
//! An implementation of the [Tango] distributed control system, written from scratch in
//! Rust, for writing clients and device servers.
//!
//! The protocol actually used to reach a device is a detail of the crate rather than of
//! the code using it: a [`dev::DevProxy`] talks to whatever backend can reach its target,
//! and a [`server::Server`] serves its devices on every backend able to serve them.
//!
//! Every call is blocking, up to the timeout of the proxy or the deadline of the request:
//! there is no runtime to install. Each one also has an asynchronous `*_async` form, which
//! runs on any executor, so that a single thread can wait on many devices at once; either
//! way, the backend multiplexes the concurrent requests over the connection it shares.
//!
//! # Client
//!
//! A client asks a device for what it wants and says which type it expects, one name
//! giving one value and a tuple of names giving as many, in a single request.
//!
//! ```no_run
//! use tango::dev::DevProxy;
//! use tango::error::Result;
//!
//! fn main() -> Result<()> {
//!
//!     // The device is looked up in the database given by `TANGO_HOST`, the connection
//!     // being made on the first request and kept for the following ones.
//!     let dev = DevProxy::new("sys/tg_test/1");
//!     println!("{} is {:?}", dev.name()?, dev.state()?);
//!
//!     // A reading carries the value, the write value, the quality and the timestamp.
//!     let read = dev.read_attr::<f64, _>("double_scalar")?;
//!     println!("double_scalar = {:?} ({:?})", read.value, read.quality);
//!
//!     dev.write_attr(("double_scalar", 3.14))?;
//!
//!     // A command is typed the same way, on both of its sides, `()` being no data.
//!     let echo: String = dev.command("DevString", "hello")?;
//!     println!("DevString -> {echo}");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Server
//!
//! A device server is a plain Rust struct, its model, and the functions of it that the
//! attributes and the commands of the device are defined from. Nothing is implemented on
//! the model and no macro is involved: a read function is given a shared access to it, a
//! write or an exclusive command an exclusive one, and the server takes care of the lock.
//!
//! ```no_run
//! use tango::server::{AttrDef, ClassDef, CommandDef, Dev, ServerBuilder};
//! use tango::error::Result;
//!
//! /// The model of one device, owned by the server serving it.
//! struct Counter {
//!     count: i32,
//! }
//!
//! impl Counter {
//!
//!     /// Build the model of a device, and give it its interface.
//!     fn init(dev: &Dev<Self>) -> Result<Self> {
//!
//!         dev.add_attr(AttrDef::new("count")
//!             .doc("The current value of the counter.")
//!             .read(Counter::count))?;
//!
//!         dev.add_command(CommandDef::new("Add")
//!             .in_doc("How much to add to the counter.")
//!             .out_doc("The value of the counter afterwards.")
//!             .exec_exclusive(Counter::add))?;
//!
//!         Ok(Self { count: 0 })
//!     }
//!
//!     /// Read the attribute, sharing the model with the other readers.
//!     fn count(&self, _dev: &Dev<Self>) -> Result<i32> {
//!         Ok(self.count)
//!     }
//!
//!     /// Execute the command, alone on the model for the time it takes.
//!     fn add(&mut self, _dev: &Dev<Self>, value: i32) -> Result<i32> {
//!         self.count += value;
//!         Ok(self.count)
//!     }
//!
//! }
//!
//! /// Serve the devices the database lists for this server until it is stopped.
//! fn main() -> Result<()> {
//!     ServerBuilder::from_args()
//!         .class(ClassDef::new("Counter", Counter::init))?
//!         .run()
//! }
//! ```
//!
//! The server is named after its executable, as cppTango does, and its instance is taken
//! from the command line, so that a `Counter` executable is launched as the `Counter/test`
//! server with `Counter test`, or with `Counter test --dev test/counter/1` to serve a
//! database of its own for testing, with that device in it, see
//! [`server::ServerArgs`].
//!
//! [Tango]: https://www.tango-controls.org/

mod future;
mod pool;
pub mod name;
pub mod buf;

pub mod value;
pub mod prop;

mod local;
pub mod dev;
pub mod error;
pub mod database;
pub mod backend;

pub mod server;
pub mod testing;

pub mod corba;