dnp3 1.6.0

Rust implementation of DNP3 (IEEE 1815) with idiomatic bindings for C, C++, .NET, and Java
Documentation
use crate::decode::DecodeLevel;
use crate::link::error::LinkError;
use crate::link::header::FrameInfo;
use crate::link::reader::LinkModes;
use crate::link::EndpointAddress;
use crate::outstation::Feature;
use crate::transport::{Fragment, FragmentAddr, FragmentInfo, TransportData};
use crate::util::buffer::Buffer;
use crate::util::phys::{PhysAddr, PhysLayer};

pub(crate) struct MockReader {
    num_reads: usize,
    count: usize,
    frame_id: u32,
    info: Option<FrameInfo>,
    buffer: Buffer,
}

impl MockReader {
    pub(crate) fn master(_: LinkModes, _: EndpointAddress, rx_buffer_size: usize) -> Self {
        Self::new(rx_buffer_size)
    }

    pub(crate) fn outstation(
        _: LinkModes,
        _: EndpointAddress,
        _self_address: Feature,
        rx_buffer_size: usize,
    ) -> Self {
        Self::new(rx_buffer_size)
    }

    fn new(buffer_size: usize) -> Self {
        Self {
            num_reads: 0,
            count: 0,
            frame_id: 0,
            info: None,
            buffer: Buffer::new(buffer_size),
        }
    }

    pub(crate) fn set_rx_frame_info(&mut self, info: FrameInfo) {
        self.info = Some(info)
    }

    pub(crate) fn num_reads(&self) -> usize {
        self.num_reads
    }

    pub(crate) fn reset(&mut self) {}

    pub(crate) fn seed_link(&mut self, _: &[u8]) -> Result<(), scursor::WriteError> {
        unimplemented!()
    }

    pub(crate) fn peek(&self) -> Option<TransportData> {
        Some(TransportData::Fragment(self.get(self.count)?))
    }

    pub(crate) fn pop(&mut self) -> Option<TransportData> {
        let count = self.count;
        self.count = 0;
        Some(TransportData::Fragment(self.get(count)?))
    }

    fn get(&self, count: usize) -> Option<Fragment> {
        if count == 0 {
            return None;
        }
        let info = self
            .info
            .expect("call set_rx_frame_info(..) before running test");
        let addr = FragmentAddr {
            link: info.source,
            phys: PhysAddr::None,
        };
        let fragment = Fragment {
            info: FragmentInfo::new(self.frame_id, addr, info.broadcast),
            data: self.buffer.get(count).unwrap(),
        };
        Some(fragment)
    }

    pub(crate) async fn read(
        &mut self,
        io: &mut PhysLayer,
        level: DecodeLevel,
    ) -> Result<(), LinkError> {
        if self.count > 0 {
            return Ok(());
        }

        self.num_reads += 1;
        let (count, _) = io
            .read(
                self.buffer.get_mut(self.buffer.len()).unwrap(),
                level.physical,
            )
            .await?;
        self.count = count;
        self.frame_id = self.frame_id.wrapping_add(1);
        Ok(())
    }
}