use core::marker::PhantomData;
use crate::core::time::milliseconds;
use crate::core::Priority;
use crate::{Node, PublishError, StartSendError};
use canadensis_core::nb;
use canadensis_core::transport::Transmitter;
use canadensis_data_types::uavcan::node::port::list_1_0::{List, SUBJECT};
use canadensis_data_types::uavcan::node::port::service_id_list_1_0::ServiceIDList;
use canadensis_data_types::uavcan::node::port::subject_id_1_0::SubjectID;
use canadensis_data_types::uavcan::node::port::subject_id_list_1_0::SubjectIDList;
use canadensis_encoding::bits::BitArray;
pub struct PortListService<N> {
_node: PhantomData<N>,
}
impl<N> PortListService<N>
where
N: Node,
{
pub fn new(node: &mut N) -> Result<Self, NewError<N>> {
if node.node_id().is_none() {
return Err(NewError::Anonymous);
}
node.start_publishing(SUBJECT, milliseconds(10000), Priority::Optional.into())
.map_err(|err| match err {
StartSendError::Memory(_) => NewError::OutOfMemory,
StartSendError::Duplicate => NewError::Duplicate,
StartSendError::Transport(err) => NewError::Other(err),
StartSendError::AnonymousRequest => unreachable!(), })?;
Ok(Self { _node: PhantomData })
}
pub fn publish_port_list(
&mut self,
node: &mut N,
) -> nb::Result<(), PublishError<<N::Transmitter as Transmitter<N::Clock>>::Error>> {
node.publish(
SUBJECT,
&List {
publishers: SubjectIDList::SparseList(
node.publishers()
.map(|x| SubjectID { value: x.into() })
.collect(),
),
subscribers: SubjectIDList::SparseList(
node.subscribers()
.map(|x| SubjectID { value: x.into() })
.collect(),
),
clients: ServiceIDList {
mask: node.clients().fold(BitArray::new(512), |mut bits, x| {
bits.set(x.into(), true);
bits
}),
},
servers: ServiceIDList {
mask: node.servers().fold(BitArray::new(512), |mut bits, x| {
bits.set(x.into(), true);
bits
}),
},
},
)
}
}
pub enum NewError<N: Node> {
OutOfMemory,
Duplicate,
Other(<N::Transmitter as Transmitter<N::Clock>>::Error),
Anonymous,
}