brec/packet/
read.rs

1use crate::*;
2
3/// Reads a complete `PacketDef` from a stream, including header, blocks, and optional payload.
4///
5/// This implementation **does not support partial reads** — if the header is successfully
6/// read but the blocks or payload data are incomplete, an I/O error will be returned.
7///
8/// # Notes
9/// - Does **not** return `Error::NotEnoughData`; instead, read failures always result in `std::io::Error`.
10/// - Use this implementation when you're sure the entire packet is available in the stream.
11///
12/// # Errors
13/// - `Error::SignatureDismatch` or `Error::CrcDismatch` if header validation fails.
14/// - `Error::NotEnoughData` if there’s insufficient data in the inner block stream.
15/// - `Error::MaxBlocksCount` if the block count exceeds the allowed maximum.
16/// - Any decoding or payload-related error from underlying implementations.
17impl<B: BlockDef, P: PayloadDef<Inner>, Inner: PayloadInnerDef> ReadFrom
18    for PacketDef<B, P, Inner>
19{
20    fn read<T: std::io::Read>(buf: &mut T) -> Result<Self, Error>
21    where
22        Self: Sized,
23    {
24        let header = PacketHeader::read(buf)?;
25        let mut pkg = PacketDef::default();
26        let mut read = 0;
27        let mut inner = vec![0u8; header.size as usize];
28        buf.read_exact(&mut inner)?;
29        let mut reader = std::io::Cursor::new(&mut inner);
30        if header.blocks_len > 0 {
31            let mut iterations = 0;
32            loop {
33                match <B as TryReadFromBuffered>::try_read(&mut reader)? {
34                    ReadStatus::Success(blk) => {
35                        read += blk.size();
36                        pkg.blocks.push(blk);
37                        if read == header.blocks_len {
38                            break;
39                        }
40                    }
41                    ReadStatus::NotEnoughData(needed) => {
42                        return Err(Error::NotEnoughData(needed as usize));
43                    }
44                }
45                iterations += 1;
46                if iterations > MAX_BLOCKS_COUNT as usize {
47                    return Err(Error::MaxBlocksCount);
48                }
49            }
50        }
51        if header.payload {
52            let header = <PayloadHeader as ReadFrom>::read(&mut reader)?;
53            let payload = <P as ExtractPayloadFrom<Inner>>::read(&mut reader, &header)?;
54            pkg.payload = Some(payload);
55        }
56        Ok(pkg)
57    }
58}
59
60/// Attempts to read a `PacketDef` from a seekable stream with partial read awareness.
61///
62/// This implementation checks if enough data is available before attempting to decode,
63/// and can return `ReadStatus::NotEnoughData(...)` instead of failing with an I/O error.
64///
65/// # Behavior
66/// - If not enough data is available for the entire payload, stream position is reset.
67/// - If read fails partway through (block or payload), stream position is reset and the error returned.
68/// - If block count exceeds `MAX_BLOCKS_COUNT`, returns `Error::MaxBlocksCount`.
69///
70/// # Returns
71/// - `ReadStatus::Success(packet)` — full packet successfully read.
72/// - `ReadStatus::NotEnoughData(bytes)` — more data needed to complete the packet.
73/// - `Error` — on decoding, CRC, signature, or logic errors.
74///
75/// # Stream behavior
76/// Seeks forward to read the packet, and seeks back on early return or error.
77impl<B: BlockDef, P: PayloadDef<Inner>, Inner: PayloadInnerDef> TryReadFrom
78    for PacketDef<B, P, Inner>
79{
80    fn try_read<T: std::io::Read + std::io::Seek>(buf: &mut T) -> Result<ReadStatus<Self>, Error>
81    where
82        Self: Sized,
83    {
84        let start_pos = buf.stream_position()?;
85        let available = buf.seek(std::io::SeekFrom::End(0))? - start_pos;
86        buf.seek(std::io::SeekFrom::Start(start_pos))?;
87        let header = match <PacketHeader as TryReadFrom>::try_read(buf)? {
88            ReadStatus::NotEnoughData(needed) => return Ok(ReadStatus::NotEnoughData(needed)),
89            ReadStatus::Success(header) => header,
90        };
91        if header.size > available {
92            return Ok(ReadStatus::NotEnoughData(header.size - available));
93        }
94        let mut pkg = PacketDef::default();
95        let mut read = 0;
96        if header.blocks_len > 0 {
97            let mut iterations = 0;
98            loop {
99                match <B as TryReadFrom>::try_read(buf) {
100                    Ok(ReadStatus::Success(blk)) => {
101                        read += blk.size();
102                        pkg.blocks.push(blk);
103                        if read == header.blocks_len {
104                            break;
105                        }
106                    }
107                    Ok(ReadStatus::NotEnoughData(needed)) => {
108                        buf.seek(std::io::SeekFrom::Start(start_pos))?;
109                        return Ok(ReadStatus::NotEnoughData(needed));
110                    }
111                    Err(err) => {
112                        buf.seek(std::io::SeekFrom::Start(start_pos))?;
113                        return Err(err);
114                    }
115                }
116                iterations += 1;
117                if iterations > MAX_BLOCKS_COUNT as usize {
118                    buf.seek(std::io::SeekFrom::Start(start_pos))?;
119                    return Err(Error::MaxBlocksCount);
120                }
121            }
122        }
123        if header.payload {
124            match <PayloadHeader as TryReadFrom>::try_read(buf)? {
125                ReadStatus::Success(header) => {
126                    match <P as TryExtractPayloadFrom<Inner>>::try_read(buf, &header) {
127                        Ok(ReadStatus::Success(payload)) => {
128                            pkg.payload = Some(payload);
129                        }
130                        Ok(ReadStatus::NotEnoughData(needed)) => {
131                            buf.seek(std::io::SeekFrom::Start(start_pos))?;
132                            return Ok(ReadStatus::NotEnoughData(needed));
133                        }
134                        Err(err) => {
135                            buf.seek(std::io::SeekFrom::Start(start_pos))?;
136                            return Err(err);
137                        }
138                    }
139                }
140                ReadStatus::NotEnoughData(needed) => {
141                    buf.seek(std::io::SeekFrom::Start(start_pos))?;
142                    return Err(Error::NotEnoughData(needed as usize));
143                }
144            }
145        }
146        Ok(ReadStatus::Success(pkg))
147    }
148}
149
150/// Attempts to read a `PacketDef` from a buffered reader.
151///
152/// This is similar to `TryReadFrom`, but works with non-seekable buffered sources (e.g., network streams).
153///
154/// # Behavior
155/// - Reads header directly from `BufRead::fill_buf()` and consumes it.
156/// - Ensures that `header.size` bytes are available before decoding.
157/// - Supports partial reads using `ReadStatus::NotEnoughData(...)`.
158///
159/// # Returns
160/// - `ReadStatus::Success(packet)` — if all required data was read and validated.
161/// - `ReadStatus::NotEnoughData(bytes)` — if more bytes are needed.
162/// - `Error::MaxBlocksCount` — if the block limit is exceeded.
163/// - Any decoding or CRC/signature errors.
164///
165/// # Notes
166/// The header and block stream are parsed directly from the internal buffer. Payload data may be buffered or streamed depending on implementation.
167impl<B: BlockDef, P: PayloadDef<Inner>, Inner: PayloadInnerDef> TryReadFromBuffered
168    for PacketDef<B, P, Inner>
169{
170    fn try_read<T: std::io::BufRead>(reader: &mut T) -> Result<ReadStatus<Self>, Error>
171    where
172        Self: Sized,
173    {
174        let bytes = reader.fill_buf()?;
175        let available = bytes.len() as u64;
176        if available < PacketHeader::ssize() {
177            return Ok(ReadStatus::NotEnoughData(PacketHeader::ssize() - available));
178        }
179        let header = PacketHeader::read_from_slice(bytes, false)?;
180        if header.size > available {
181            return Ok(ReadStatus::NotEnoughData(header.size - available));
182        }
183        reader.consume(PacketHeader::ssize() as usize);
184        let mut pkg = PacketDef::default();
185        let mut read = 0;
186        if header.blocks_len > 0 {
187            let mut iterations = 0;
188            loop {
189                match <B as TryReadFromBuffered>::try_read(reader)? {
190                    ReadStatus::Success(blk) => {
191                        read += blk.size();
192                        pkg.blocks.push(blk);
193                        if read == header.blocks_len {
194                            break;
195                        }
196                    }
197                    ReadStatus::NotEnoughData(needed) => {
198                        return Ok(ReadStatus::NotEnoughData(needed))
199                    }
200                }
201                iterations += 1;
202                if iterations > MAX_BLOCKS_COUNT as usize {
203                    return Err(Error::MaxBlocksCount);
204                }
205            }
206        }
207        if header.payload {
208            match <PayloadHeader as TryReadFromBuffered>::try_read(reader)? {
209                ReadStatus::Success(header) => {
210                    reader.consume(header.size());
211                    match <P as TryExtractPayloadFromBuffered<Inner>>::try_read(reader, &header)? {
212                        ReadStatus::Success(payload) => {
213                            pkg.payload = Some(payload);
214                        }
215                        ReadStatus::NotEnoughData(needed) => {
216                            return Ok(ReadStatus::NotEnoughData(needed))
217                        }
218                    }
219                }
220                ReadStatus::NotEnoughData(needed) => {
221                    return Err(Error::NotEnoughData(needed as usize))
222                }
223            }
224        }
225        Ok(ReadStatus::Success(pkg))
226    }
227}