blob_stream/
protocol_front.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/nimble-rust/nimble
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::protocol::{AckChunkData, SetChunkData, StartTransferData, TransferId};
6use flood_rs::{ReadOctetStream, WriteOctetStream};
7use std::io;
8use std::io::ErrorKind;
9
10#[derive(Debug, Clone, Eq, PartialEq)]
11pub struct SetChunkFrontData {
12    pub transfer_id: TransferId,
13    pub data: SetChunkData,
14}
15
16impl SetChunkFrontData {
17    /// # Errors
18    ///
19    /// This function will return an `io::Error` if there is an issue with writing to the stream.
20    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
21    #[allow(clippy::cast_possible_truncation)]
22    pub fn to_stream(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
23        self.transfer_id.to_stream(stream)?;
24        self.data.to_stream(stream)?;
25        Ok(())
26    }
27
28    /// # Errors
29    ///
30    /// This function will return an `io::Error` if there is an issue with writing to the stream.
31    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
32    pub fn from_stream(stream: &mut impl ReadOctetStream) -> io::Result<Self> {
33        Ok(Self {
34            transfer_id: TransferId::from_stream(stream)?,
35            data: SetChunkData::from_stream(stream)?,
36        })
37    }
38}
39
40#[derive(Debug, Clone, Eq, PartialEq)]
41pub enum SenderToReceiverFrontCommands {
42    SetChunk(SetChunkFrontData),
43    StartTransfer(StartTransferData),
44}
45
46#[repr(u8)]
47enum SenderToReceiverFrontCommand {
48    SetChunk = 0x01,
49    StartTransfer = 0x02,
50}
51
52impl TryFrom<u8> for SenderToReceiverFrontCommand {
53    type Error = io::Error;
54
55    fn try_from(value: u8) -> io::Result<Self> {
56        match value {
57            0x01 => Ok(Self::SetChunk),
58            0x02 => Ok(Self::StartTransfer),
59            _ => Err(io::Error::new(
60                io::ErrorKind::InvalidData,
61                format!("Unknown command {value}"),
62            )),
63        }
64    }
65}
66
67impl SenderToReceiverFrontCommands {
68    #[must_use]
69    pub const fn to_octet(&self) -> u8 {
70        match self {
71            Self::SetChunk(_) => SenderToReceiverFrontCommand::SetChunk as u8,
72            Self::StartTransfer(_) => SenderToReceiverFrontCommand::StartTransfer as u8,
73        }
74    }
75
76    /// # Errors
77    ///
78    /// This function will return an `io::Error` if there is an issue with writing to the stream.
79    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
80
81    pub fn to_stream(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
82        stream.write_u8(self.to_octet())?;
83        match self {
84            Self::SetChunk(set_chunk_header) => set_chunk_header.to_stream(stream),
85            Self::StartTransfer(transfer_data) => transfer_data.to_stream(stream),
86        }
87    }
88
89    /// # Errors
90    ///
91    /// This function will return an `io::Error` if there is an issue with writing to the stream.
92    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
93    pub fn from_stream(stream: &mut impl ReadOctetStream) -> io::Result<Self> {
94        let command_value = stream.read_u8()?;
95        let command = SenderToReceiverFrontCommand::try_from(command_value)?;
96        let x = match command {
97            SenderToReceiverFrontCommand::SetChunk => {
98                Self::SetChunk(SetChunkFrontData::from_stream(stream)?)
99            }
100            SenderToReceiverFrontCommand::StartTransfer => {
101                Self::StartTransfer(StartTransferData::from_stream(stream)?)
102            }
103        };
104        Ok(x)
105    }
106}
107
108#[repr(u8)]
109enum ReceiverToSenderFrontCommand {
110    AckChunk = 0x02,
111    AckStart = 0x03,
112}
113
114impl TryFrom<u8> for ReceiverToSenderFrontCommand {
115    type Error = io::Error;
116
117    fn try_from(value: u8) -> io::Result<Self> {
118        match value {
119            0x02 => Ok(Self::AckChunk),
120            0x03 => Ok(Self::AckStart),
121            _ => Err(io::Error::new(
122                ErrorKind::InvalidData,
123                format!("Unknown command {value}"),
124            )),
125        }
126    }
127}
128
129#[derive(Debug, Clone, Eq, PartialEq)]
130pub struct AckChunkFrontData {
131    pub transfer_id: TransferId,
132    pub data: AckChunkData,
133}
134
135impl AckChunkFrontData {
136    /// # Errors
137    ///
138    /// This function will return an `io::Error` if there is an issue with writing to the stream.
139    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
140    pub fn to_stream(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
141        self.transfer_id.to_stream(stream)?;
142        self.data.to_stream(stream)
143    }
144
145    /// # Errors
146    ///
147    /// This function will return an `io::Error` if there is an issue with writing to the stream.
148    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
149    pub fn from_stream(stream: &mut impl ReadOctetStream) -> io::Result<Self> {
150        Ok(Self {
151            transfer_id: TransferId::from_stream(stream)?,
152            data: AckChunkData::from_stream(stream)?,
153        })
154    }
155}
156
157#[derive(Debug, Clone, Eq, PartialEq)]
158pub enum ReceiverToSenderFrontCommands {
159    AckChunk(AckChunkFrontData),
160    AckStart(u16),
161}
162
163impl ReceiverToSenderFrontCommands {
164    #[must_use]
165    pub const fn to_octet(&self) -> u8 {
166        match self {
167            Self::AckChunk(_) => ReceiverToSenderFrontCommand::AckChunk as u8,
168            Self::AckStart(_) => ReceiverToSenderFrontCommand::AckStart as u8,
169        }
170    }
171
172    /// # Errors
173    ///
174    /// This function will return an `io::Error` if there is an issue with writing to the stream.
175    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
176    pub fn to_stream(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
177        stream.write_u8(self.to_octet())?;
178        match self {
179            Self::AckChunk(set_chunk_header) => set_chunk_header.to_stream(stream),
180            Self::AckStart(transfer_id) => stream.write_u16(*transfer_id),
181        }
182    }
183
184    /// # Errors
185    ///
186    /// This function will return an `io::Error` if there is an issue with writing to the stream.
187    /// This could happen if the stream is closed or if there are underlying I/O errors during the write operation.
188    pub fn from_stream(stream: &mut impl ReadOctetStream) -> io::Result<Self> {
189        let command_value = stream.read_u8()?;
190        let command = ReceiverToSenderFrontCommand::try_from(command_value)?;
191        let x = match command {
192            ReceiverToSenderFrontCommand::AckChunk => Self::AckChunk(AckChunkFrontData {
193                transfer_id: TransferId::from_stream(stream)?,
194                data: AckChunkData::from_stream(stream)?,
195            }),
196            ReceiverToSenderFrontCommand::AckStart => Self::AckStart(stream.read_u16()?),
197        };
198        Ok(x)
199    }
200}