use cameleon_genapi::{
elem_type::{DisplayNotation, FloatRepresentation, IntegerRepresentation},
interface::IncrementMode,
prelude::*,
GenApiError, GenApiResult, NodeId,
};
use super::{DeviceControl, GenApiCtxt, GenApiDevice, ParamsCtxt};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IntegerNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FloatNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StringNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumerationNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CommandNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BooleanNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RegisterNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CategoryNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PortNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumEntryNode(NodeId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Node(pub(super) NodeId);
impl From<NodeId> for Node {
fn from(nid: NodeId) -> Self {
Node(nid)
}
}
macro_rules! delegate {
(
$expect_kind:ident,
$(
$(#[$meta:meta])*
$vis:vis fn $method:ident<$Ctrl:ident, $Ctxt:ident>($self:ident, ctxt: &mut ParamsCtxt<Ctrl, Ctxt> $(,$arg:ident: $arg_ty:ty)*) -> $ret_ty:ty,)*) => {
$(
$(#[$meta])*
$vis fn $method<$Ctrl, $Ctxt>($self, ctxt: &mut ParamsCtxt<$Ctrl, $Ctxt> $(,$arg: $arg_ty)*) -> $ret_ty
where $Ctrl: DeviceControl,
$Ctxt: GenApiCtxt
{
ctxt.enter2(|ctrl, ns, vc| {
let mut device = GenApiDevice::new(ctrl);
$self.0
.$expect_kind(ns)
.unwrap()
.$method($($arg,)* &mut device, ns, vc)
})
}
)*
};
(
no_vc,
$expect_kind:ident,
$(
$(#[$meta:meta])*
$vis:vis fn $method:ident<$Ctrl:ident, $Ctxt:ident>($self:ident, ctxt: &ParamsCtxt<Ctrl, Ctxt> $(,$arg:ident: $arg_ty:ty)*) -> $ret_ty:ty,)*) => {
$(
$(#[$meta])*
$vis fn $method<$Ctrl, $Ctxt>($self, ctxt: &ParamsCtxt<$Ctrl, $Ctxt> $(,$arg: $arg_ty)*) -> $ret_ty
where
$Ctxt: GenApiCtxt
{
let ns = ctxt.node_store();
$self.0.$expect_kind(ns).unwrap().$method($($arg,)* ns)
}
)*
};
}
impl IntegerNode {
delegate! {
expect_iinteger_kind,
pub fn value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<i64>,
pub fn set_value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: i64) -> GenApiResult<()>,
pub fn min<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<i64>,
pub fn set_min<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: i64) -> GenApiResult<()>,
pub fn max<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<i64>,
pub fn set_max<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: i64) -> GenApiResult<()>,
pub fn inc<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<Option<i64>>,
pub fn is_readable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_writable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
delegate! {
no_vc,
expect_iinteger_kind,
pub fn inc_mode<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<IncrementMode>,
pub fn representation<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> IntegerRepresentation,
}
pub fn unit<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<String>
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0
.expect_iinteger_kind(ns)
.unwrap()
.unit(ns)
.map(String::from)
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl FloatNode {
delegate! {
expect_ifloat_kind,
pub fn value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<f64>,
pub fn set_value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: f64) -> GenApiResult<()>,
pub fn min<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<f64>,
pub fn max<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<f64>,
pub fn inc<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<Option<f64>>,
pub fn is_readable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_writable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
delegate! {
no_vc,
expect_ifloat_kind,
pub fn inc_mode<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<IncrementMode>,
pub fn representation<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) ->FloatRepresentation,
pub fn display_notation<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> DisplayNotation,
}
pub fn unit<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<String>
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0
.expect_ifloat_kind(ns)
.unwrap()
.unit(ns)
.map(String::from)
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl StringNode {
delegate! {
expect_istring_kind,
pub fn value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<String>,
pub fn set_value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: String) -> GenApiResult<()>,
pub fn max_length<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<i64>,
pub fn is_readable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_writable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl EnumerationNode {
delegate! {
expect_ienumeration_kind,
pub fn set_entry_by_symbolic<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, name: &str) -> GenApiResult<()>,
pub fn set_entry_by_value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: i64) -> GenApiResult<()>,
pub fn is_readable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_writable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
pub fn entries<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Vec<EnumEntryNode>
where
Ctrl: DeviceControl,
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0
.expect_ienumeration_kind(ns)
.unwrap()
.entries(ns)
.iter()
.map(|nid| EnumEntryNode(*nid))
.collect()
}
pub fn current_entry<Ctrl, Ctxt>(
self,
ctxt: &mut ParamsCtxt<Ctrl, Ctxt>,
) -> GenApiResult<EnumEntryNode>
where
Ctrl: DeviceControl,
Ctxt: GenApiCtxt,
{
let value = ctxt.enter2(|ctrl, ns, vc| {
let mut device = GenApiDevice::new(ctrl);
self.0
.expect_ienumeration_kind(ns)
.unwrap()
.current_value(&mut device, ns, vc)
})?;
let entries = self.entries(ctxt);
entries
.into_iter()
.find(|ent| ent.value(ctxt) == value)
.ok_or_else(|| {
GenApiError::InvalidNode(
format!(
"no entry found corresponding to the current value of {}",
self.as_node().name(ctxt),
)
.into(),
)
})
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl EnumEntryNode {
delegate! {
expect_enum_entry,
pub fn is_locked<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_implemented<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_available<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
pub fn value<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> i64
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0.expect_enum_entry(ns).unwrap().value()
}
pub fn symbolic<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> &str
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0.expect_enum_entry(ns).unwrap().symbolic()
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl CommandNode {
delegate! {
expect_icommand_kind,
pub fn execute<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<()>,
pub fn is_done<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_writable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl BooleanNode {
delegate! {
expect_iboolean_kind,
pub fn value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn set_value<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, value: bool) -> GenApiResult<()>,
pub fn is_readable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
pub fn is_writable<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<bool>,
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl RegisterNode {
delegate! {
expect_iregister_kind,
pub fn read<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, buf: &mut [u8]) -> GenApiResult<()>,
pub fn write<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, data: &[u8]) -> GenApiResult<()>,
pub fn address<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<i64>,
pub fn length<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> GenApiResult<i64>,
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl CategoryNode {
pub fn nodes<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>) -> Vec<Node>
where
Ctrl: DeviceControl,
Ctxt: GenApiCtxt,
{
ctxt.enter2(|_, ns, _| {
self.0
.expect_icategory_kind(ns)
.unwrap()
.nodes(ns)
.iter()
.map(|nid| Node(*nid))
.collect()
})
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
impl PortNode {
delegate! {
expect_iport_kind,
pub fn read<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, address: i64, buf: &mut [u8]) -> GenApiResult<()>,
pub fn write<Ctrl, Ctxt>(self, ctxt: &mut ParamsCtxt<Ctrl, Ctxt>, address: i64, data: &[u8]) -> GenApiResult<()>,
}
pub fn as_node(self) -> Node {
Node(self.0)
}
}
macro_rules! downcast {
($(
$(#[$meta:meta])*
($method:ident, $expect_kind:ident, $ty:ident),
)*
) => {
$(
$(#[$meta])*
pub fn $method<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<$ty>
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0.$expect_kind(ns).map(|_| $ty(self.0))
})*
};
}
macro_rules! delegate_node_base {
(
$(
$(#[$meta:meta])*
$vis:vis fn $method:ident<$Ctrl:ident, $Ctxt:ident>($self:ident, ctxt: &ParamsCtxt<Ctrl, Ctxt> $(,$arg:ident: $arg_ty:ty)*) -> $ret_ty:ty,)*) => {
$(
$(#[$meta])*
$vis fn $method<$Ctrl, $Ctxt>($self, ctxt: &ParamsCtxt<$Ctrl, $Ctxt> $(,$arg: $arg_ty)*) -> $ret_ty
where
$Ctxt: GenApiCtxt
{
let ns = ctxt.node_store();
let node_base = $self.0.as_inode_kind(ns).unwrap().node_base_precise();
node_base.$method($($arg,)*).into()
}
)*
};
}
impl Node {
downcast! {
(as_integer, as_iinteger_kind, IntegerNode),
(as_float, as_ifloat_kind, FloatNode),
(as_string ,as_istring_kind, StringNode),
(as_enumeration ,as_ienumeration_kind, EnumerationNode),
(as_enum_entry, as_enum_entry, EnumEntryNode),
(as_command, as_icommand_kind, CommandNode),
(as_boolean, as_iboolean_kind, BooleanNode),
(as_register, as_iregister_kind, RegisterNode),
(as_category, as_icategory_kind, CategoryNode),
(as_port, as_iport_kind, PortNode),
}
pub fn name<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> &str
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
self.0.as_inode_kind(ns).unwrap().name(ns)
}
pub fn display_name<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> &str
where
Ctxt: GenApiCtxt,
{
let ns = ctxt.node_store();
let node_base = self.0.as_inode_kind(ns).unwrap().node_base_precise();
if let Some(desc) = node_base.display_name() {
desc
} else {
self.name(ctxt)
}
}
delegate_node_base! {
pub fn name_space<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> super::NameSpace,
pub fn description<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<&str>,
pub fn expose_static<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<bool>,
pub fn visibility<Ctrl, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> super::Visibility,
pub fn is_deprecated<Ctlr, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> bool,
pub fn event_id<Ctlr, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<u64>,
pub fn tooltip<Ctlr, Ctxt>(self, ctxt: &ParamsCtxt<Ctrl, Ctxt>) -> Option<&str>,
}
}