use crate::canmessage::CanMessageRef;
use crate::error::Result;
use mdflib_sys as ffi;
use std::marker::PhantomData;
#[derive(Debug, Clone, Copy)]
pub struct CanBusObserverRef<'a> {
pub(crate) inner: *const ffi::CanBusObserver,
_marker: PhantomData<&'a ()>,
}
impl std::fmt::Display for CanBusObserverRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"CanBusObserver {{ name: '{}', nof_samples: {} }}",
self.get_name(),
self.get_nof_samples()
)
}
}
impl<'a> CanBusObserverRef<'a> {
#[allow(dead_code)]
pub(crate) fn new(inner: *const ffi::CanBusObserver) -> Self {
Self {
inner,
_marker: PhantomData,
}
}
pub fn get_name(&self) -> String {
let mut buffer = vec![0u8; 256];
let len = unsafe {
ffi::CanBusObserverGetName(
self.inner as *mut ffi::CanBusObserver,
buffer.as_mut_ptr() as *mut i8,
buffer.len(),
)
};
if len > 0 && len < buffer.len() {
buffer.truncate(len);
String::from_utf8_lossy(&buffer).to_string()
} else {
String::new()
}
}
pub fn get_nof_samples(&self) -> usize {
unsafe { ffi::CanBusObserverGetNofSamples(self.inner) }
}
pub fn get_can_message(&self, sample: usize) -> Option<CanMessageRef<'a>> {
let can_msg_ptr = unsafe {
ffi::CanBusObserverGetCanMessage(self.inner as *mut ffi::CanBusObserver, sample)
};
if can_msg_ptr.is_null() {
None
} else {
Some(CanMessageRef::new(can_msg_ptr))
}
}
pub fn get_all_can_messages(&self) -> Vec<Option<CanMessageRef<'a>>> {
let nof_samples = self.get_nof_samples();
let mut messages = Vec::with_capacity(nof_samples);
for sample in 0..nof_samples {
messages.push(self.get_can_message(sample));
}
messages
}
}
#[derive(Debug)]
pub struct CanBusObserver<'a> {
pub(crate) inner: *mut ffi::CanBusObserver,
_marker: PhantomData<&'a ()>,
}
impl<'a> CanBusObserver<'a> {
#[allow(dead_code)]
pub(crate) fn new(inner: *mut ffi::CanBusObserver) -> Self {
Self {
inner,
_marker: PhantomData,
}
}
}
impl<'a> std::ops::Deref for CanBusObserver<'a> {
type Target = CanBusObserverRef<'a>;
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const CanBusObserver as *const CanBusObserverRef) }
}
}
impl<'a> Drop for CanBusObserver<'a> {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe {
ffi::CanBusObserverUnInit(self.inner);
}
}
}
}
unsafe impl<'a> Send for CanBusObserver<'a> {}
unsafe impl<'a> Sync for CanBusObserver<'a> {}
pub unsafe fn create_can_bus_observer<'a>(
data_group: *const ffi::IDataGroup,
channel_group: *const ffi::IChannelGroup,
) -> Result<CanBusObserver<'a>> {
let observer = unsafe { ffi::CreateCanBusObserver(data_group, channel_group) };
if observer.is_null() {
return Err(crate::error::MdfError::NullPointer);
}
Ok(CanBusObserver::new(observer))
}