Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
enum State {
|
||||
Len {
|
||||
buf: [u8; std::mem::size_of::<u32>()],
|
||||
bytes_read: usize,
|
||||
},
|
||||
Frame {
|
||||
buf: Vec<u8>,
|
||||
frame_len: usize,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct Receiver {
|
||||
packet_pos: usize,
|
||||
state: State,
|
||||
max_frame_len: usize,
|
||||
}
|
||||
|
||||
pub enum FrameResult<'x> {
|
||||
Frame(Cow<'x, [u8]>),
|
||||
Incomplete,
|
||||
TooLarge(usize),
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
State::Len {
|
||||
buf: [0; std::mem::size_of::<u32>()],
|
||||
bytes_read: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Receiver {
|
||||
pub fn with_max_frame_len(max_frame_len: usize) -> Self {
|
||||
Receiver {
|
||||
packet_pos: 0,
|
||||
state: State::default(),
|
||||
max_frame_len,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_frame<'x>(&mut self, packet: &'x [u8]) -> FrameResult<'x> {
|
||||
if !packet.is_empty() {
|
||||
match &mut self.state {
|
||||
State::Len { buf, bytes_read } => {
|
||||
while *bytes_read < std::mem::size_of::<u32>() {
|
||||
if let Some(byte) = packet.get(self.packet_pos) {
|
||||
buf[*bytes_read] = *byte;
|
||||
*bytes_read += 1;
|
||||
self.packet_pos += 1;
|
||||
} else {
|
||||
self.packet_pos = 0;
|
||||
return FrameResult::Incomplete;
|
||||
}
|
||||
}
|
||||
let length = u32::from_be_bytes(*buf) as usize;
|
||||
if length <= self.max_frame_len {
|
||||
if let Some(frame) = packet.get(self.packet_pos..self.packet_pos + length) {
|
||||
self.packet_pos += length;
|
||||
self.state = State::default();
|
||||
FrameResult::Frame(frame.into())
|
||||
} else {
|
||||
let mut buf = Vec::with_capacity(length);
|
||||
if let Some(bytes_available) = packet.get(self.packet_pos..) {
|
||||
buf.extend(bytes_available);
|
||||
}
|
||||
self.state = State::Frame {
|
||||
buf,
|
||||
frame_len: length,
|
||||
};
|
||||
self.packet_pos = 0;
|
||||
FrameResult::Incomplete
|
||||
}
|
||||
} else {
|
||||
FrameResult::TooLarge(length)
|
||||
}
|
||||
}
|
||||
State::Frame { buf, frame_len } => {
|
||||
let bytes_pending = *frame_len - buf.len();
|
||||
if let Some(bytes) =
|
||||
packet.get(self.packet_pos..self.packet_pos + bytes_pending)
|
||||
{
|
||||
let mut buf = std::mem::take(buf);
|
||||
buf.extend(bytes);
|
||||
self.packet_pos += bytes_pending;
|
||||
self.state = State::default();
|
||||
FrameResult::Frame(buf.into())
|
||||
} else if let Some(bytes_available) = packet.get(self.packet_pos..) {
|
||||
buf.extend(bytes_available);
|
||||
self.packet_pos = 0;
|
||||
FrameResult::Incomplete
|
||||
} else {
|
||||
self.packet_pos = 0;
|
||||
FrameResult::Incomplete
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FrameResult::Incomplete
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user