use crate::ascii::*;
use crate::bcc;
use crate::buffer::Buffer;
use crate::nom_parser::node::{parse_command, CommandToken};
use crate::types::{Address, Parameter, Value};
use core::marker::PhantomData;
#[derive(Debug)]
pub struct Node {
state: InternalState,
address: Address,
read_again_param: Option<(Address, Parameter)>,
buffer: Buffer,
}
pub enum NodeState<'node> {
ReceiveData(ReceiveData<'node>),
SendData(SendData<'node>),
ReadParameter(ReadParam<'node>),
WriteParameter(WriteParam<'node>),
}
pub struct StateToken(PhantomData<()>);
impl<'a> From<ReceiveData<'a>> for NodeState<'a> {
fn from(x: ReceiveData<'a>) -> Self {
Self::ReceiveData(x)
}
}
impl<'a> From<SendData<'a>> for NodeState<'a> {
fn from(x: SendData<'a>) -> Self {
Self::SendData(x)
}
}
impl<'a> From<WriteParam<'a>> for NodeState<'a> {
fn from(x: WriteParam<'a>) -> Self {
Self::WriteParameter(x)
}
}
impl<'a> From<ReadParam<'a>> for NodeState<'a> {
fn from(x: ReadParam<'a>) -> Self {
Self::ReadParameter(x)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
enum InternalState {
Recv,
Send,
Read {
address: Address,
parameter: Parameter,
},
Write {
address: Address,
parameter: Parameter,
value: Value,
},
}
impl Node {
pub fn new(address: Address) -> Self {
Self {
state: InternalState::Recv,
address,
read_again_param: None,
buffer: Buffer::new(),
}
}
pub fn reset(&mut self) -> StateToken {
ReceiveData::from_state(self);
StateToken(PhantomData)
}
pub fn state(&mut self, token: StateToken) -> NodeState<'_> {
let _ = token;
match self.state {
InternalState::Recv => ReceiveData::from_state(self).into(),
InternalState::Send => SendData::from_state(self).into(),
InternalState::Read { address, parameter } => {
ReadParam::from_state(self, address, parameter).into()
}
InternalState::Write {
address,
parameter,
value,
} => WriteParam::from_state(self, address, parameter, value).into(),
}
}
fn set_state(&mut self, state: InternalState) {
self.state = state;
}
pub fn no_reply(&mut self, _token: StateToken) -> StateToken {
self.reset()
}
}
#[derive(Debug)]
pub struct ReceiveData<'node> {
node: &'node mut Node,
}
impl<'node> ReceiveData<'node> {
fn from_state(node: &'node mut Node) -> Self {
if node.state != InternalState::Recv {
node.buffer.clear();
}
node.set_state(InternalState::Recv);
Self { node }
}
pub fn receive_data(self, data: &[u8]) -> StateToken {
self.node.buffer.write(data);
self.parse_buffer();
StateToken(PhantomData)
}
fn parse_buffer(self) -> NodeState<'node> {
use CommandToken::{
InvalidPayload, ReadAgain, ReadNext, ReadParameter, ReadPrevious, WriteParameter,
};
let buffer = &mut self.node.buffer;
let (token, read_again_param) = loop {
match parse_command(buffer.as_ref()) {
(0, _) => return self.need_data(),
(consumed, token) => {
buffer.consume(consumed);
let read_again_param = self.node.read_again_param.take();
if buffer.len() == 0 {
break (token, read_again_param);
}
}
};
};
match token {
ReadParameter(address, parameter) if self.for_us(address) => {
ReadParam::from_state(self.node, address, parameter).into()
}
WriteParameter(address, parameter, value) if self.for_us(address) => {
WriteParam::from_state(self.node, address, parameter, value).into()
}
ReadAgain | ReadNext | ReadPrevious if read_again_param.is_some() => {
let (addr, last_param) = read_again_param.unwrap();
match match token {
ReadPrevious => last_param.prev(),
ReadNext => last_param.next(),
_ => Some(last_param),
} {
Some(param) => ReadParam::from_state(self.node, addr, param).into(),
None => SendData::from_byte(self.node, EOT).into(),
}
}
InvalidPayload(address) if address == self.node.address => self.send_nak(),
_ => self.need_data(), }
}
fn send_byte(self, byte: u8) -> NodeState<'node> {
SendData::from_byte(self.node, byte).into()
}
fn need_data(self) -> NodeState<'node> {
self.into()
}
fn send_nak(self) -> NodeState<'node> {
self.send_byte(NAK)
}
fn for_us(&self, address: Address) -> bool {
self.node.address == address || self.node.address == 0
}
}
#[derive(Debug)]
pub struct SendData<'node> {
node: &'node mut Node,
}
impl<'node> SendData<'node> {
fn from_state(node: &'node mut Node) -> Self {
node.set_state(InternalState::Send);
Self { node }
}
fn from_byte(node: &'node mut Node, byte: u8) -> Self {
let buf = &mut node.buffer;
buf.clear();
buf.push(byte);
Self::from_state(node)
}
pub fn send_data(&self) -> &[u8] {
self.node.buffer.as_ref()
}
pub fn data_sent(self) -> StateToken {
self.node.set_state(InternalState::Recv);
self.node.buffer.get_ref_and_clear();
StateToken(PhantomData)
}
}
#[derive(Debug)]
pub struct ReadParam<'node> {
node: &'node mut Node,
address: Address,
parameter: Parameter,
}
impl<'node> ReadParam<'node> {
fn from_state(node: &'node mut Node, address: Address, parameter: Parameter) -> Self {
node.set_state(InternalState::Read { address, parameter });
Self {
node,
address,
parameter,
}
}
pub fn send_reply_ok(self, value: Value) -> StateToken {
self.node.read_again_param = Some((self.address, self.parameter));
let data = &mut self.node.buffer;
data.clear();
data.push(STX);
data.write(&self.parameter.to_bytes());
data.write(&value.to_bytes());
data.push(ETX);
data.push(bcc(&data.as_ref()[1..]));
SendData::from_state(self.node);
StateToken(PhantomData)
}
pub fn send_invalid_parameter(self) -> StateToken {
SendData::from_byte(self.node, EOT);
StateToken(PhantomData)
}
pub fn send_read_failed(self) -> StateToken {
SendData::from_byte(self.node, NAK);
StateToken(PhantomData)
}
pub fn no_reply(self) -> StateToken {
ReceiveData::from_state(self.node);
StateToken(PhantomData)
}
pub const fn address(&self) -> Address {
self.address
}
pub const fn parameter(&self) -> Parameter {
self.parameter
}
}
#[derive(Debug)]
pub struct WriteParam<'node> {
node: &'node mut Node,
address: Address,
parameter: Parameter,
value: Value,
}
impl<'node> WriteParam<'node> {
fn from_state(
node: &'node mut Node,
address: Address,
parameter: Parameter,
value: Value,
) -> Self {
node.set_state(InternalState::Write {
address,
parameter,
value,
});
Self {
node,
address,
parameter,
value,
}
}
pub fn write_ok(self) -> StateToken {
SendData::from_byte(self.node, ACK);
StateToken(PhantomData)
}
pub fn write_error(self) -> StateToken {
SendData::from_byte(self.node, NAK);
StateToken(PhantomData)
}
pub fn no_reply(self) -> StateToken {
ReceiveData::from_state(self.node);
StateToken(PhantomData)
}
pub const fn address(&self) -> Address {
self.address
}
pub const fn parameter(&self) -> Parameter {
self.parameter
}
pub const fn value(&self) -> Value {
self.value
}
}