use crate::sys;
use crate::types::{CauseOfTransmission, TypeId};
pub struct Asdu {
#[allow(dead_code)]
buffer: sys::sCS101_StaticASDU,
#[allow(dead_code)]
ptr: sys::CS101_ASDU,
}
unsafe impl Send for Asdu {}
unsafe impl Sync for Asdu {}
impl Clone for Asdu {
fn clone(&self) -> Self {
let mut buffer = sys::sCS101_StaticASDU::default();
let ptr = unsafe { sys::CS101_ASDU_clone(self.as_ptr(), &mut buffer) };
Self { buffer, ptr }
}
}
impl Asdu {
pub unsafe fn clone_from_ptr(ptr: sys::CS101_ASDU) -> Option<Self> {
if ptr.is_null() {
return None;
}
let mut buffer = sys::sCS101_StaticASDU::default();
let cloned_ptr = sys::CS101_ASDU_clone(ptr, &mut buffer);
if cloned_ptr.is_null() {
return None;
}
Some(Self {
buffer,
ptr: cloned_ptr,
})
}
pub fn as_ptr(&self) -> sys::CS101_ASDU {
&self.buffer as *const sys::sCS101_StaticASDU as sys::CS101_ASDU
}
pub fn type_id(&self) -> Option<TypeId> {
let raw = unsafe { sys::CS101_ASDU_getTypeID(self.as_ptr()) };
TypeId::from_raw(raw)
}
pub fn type_id_raw(&self) -> sys::IEC60870_5_TypeID {
unsafe { sys::CS101_ASDU_getTypeID(self.as_ptr()) }
}
pub fn cot(&self) -> Option<CauseOfTransmission> {
let raw = unsafe { sys::CS101_ASDU_getCOT(self.as_ptr()) };
CauseOfTransmission::from_raw(raw)
}
pub fn cot_raw(&self) -> sys::CS101_CauseOfTransmission {
unsafe { sys::CS101_ASDU_getCOT(self.as_ptr()) }
}
pub fn common_address(&self) -> u16 {
unsafe { sys::CS101_ASDU_getCA(self.as_ptr()) as u16 }
}
pub fn originator_address(&self) -> u8 {
unsafe { sys::CS101_ASDU_getOA(self.as_ptr()) as u8 }
}
pub fn element_count(&self) -> usize {
unsafe { sys::CS101_ASDU_getNumberOfElements(self.as_ptr()) as usize }
}
pub fn is_test(&self) -> bool {
unsafe { sys::CS101_ASDU_isTest(self.as_ptr()) }
}
pub fn is_negative(&self) -> bool {
unsafe { sys::CS101_ASDU_isNegative(self.as_ptr()) }
}
pub fn is_sequence(&self) -> bool {
unsafe { sys::CS101_ASDU_isSequence(self.as_ptr()) }
}
pub unsafe fn get_element_raw(&self, index: usize) -> sys::InformationObject {
sys::CS101_ASDU_getElement(self.as_ptr(), index as i32)
}
}
impl std::fmt::Debug for Asdu {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Asdu")
.field("type_id", &self.type_id())
.field("cot", &self.cot())
.field("ca", &self.common_address())
.field("elements", &self.element_count())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_asdu_size() {
assert_eq!(
std::mem::size_of::<sys::sCS101_StaticASDU>(),
296,
"Static ASDU buffer should be 296 bytes"
);
}
}