Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions sv2/codec-sv2/examples/encrypted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,7 @@ fn main() {
}

// Parse the decoded frame header and payload
let decoded_frame_header = decoded_frame
.get_header()
.expect("Failed to get the frame header");
let decoded_frame_header = decoded_frame.get_header();

let decoded_msg: CustomMessage = binary_sv2::from_bytes(decoded_frame.payload())
.expect("Failed to extract the message from the payload");
Expand Down
4 changes: 1 addition & 3 deletions sv2/codec-sv2/examples/unencrypted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ fn main() {
let mut decoded_frame = receiver_side(stream_receiver);

// Parse the decoded frame header and payload
let decoded_frame_header = decoded_frame
.get_header()
.expect("Failed to get the frame header");
let decoded_frame_header = decoded_frame.get_header();
let decoded_msg: CustomMessage = binary_sv2::from_bytes(decoded_frame.payload())
.expect("Failed to extract the message from the payload");

Expand Down
14 changes: 4 additions & 10 deletions sv2/codec-sv2/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ mod prop_tests {
None => return TestResult::discard(),
};

let expected_ext_type = frame.get_header().unwrap().ext_type();
let expected_ext_type = frame.get_header().ext_type();

let mut encoder = Encoder::<TestMessage>::new();
let encoded = match encoder.encode(frame) {
Expand All @@ -526,10 +526,7 @@ mod prop_tests {
let mut decoder = StandardDecoder::<TestMessage>::new();
match decode_frame(&mut decoder, encoded.as_ref(), None) {
Some(mut decoded_frame) => {
let header = match decoded_frame.get_header() {
Some(h) => h,
None => return TestResult::failed(),
};
let header = decoded_frame.get_header();
let actual_msg_type = header.msg_type();
let actual_ext_type = header.ext_type();
let decoded_msg: TestMessage = match binary_sv2::from_bytes(decoded_frame.payload())
Expand Down Expand Up @@ -725,7 +722,7 @@ mod prop_tests {
Some(f) => f,
None => return TestResult::discard(),
};
let expected_ext = sv2_frame.get_header().unwrap().ext_type();
let expected_ext = sv2_frame.get_header().ext_type();
let frame = Frame::Sv2(sv2_frame);

let mut encoder = NoiseEncoder::<TestMessage>::new();
Expand All @@ -738,10 +735,7 @@ mod prop_tests {
let encrypted_bytes: &[u8] = encrypted.as_ref();
match decode_noise_frame(&mut decoder, &mut receiver_state, encrypted_bytes) {
Some(mut decoded) => {
let header = match decoded.get_header() {
Some(h) => h,
None => return TestResult::failed(),
};
let header = decoded.get_header();
let decoded_msg: TestMessage = match binary_sv2::from_bytes(decoded.payload()) {
Ok(m) => m,
Err(_) => return TestResult::failed(),
Expand Down
4 changes: 1 addition & 3 deletions sv2/framing-sv2/examples/sv2_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ fn main() {
.expect("Failed to deserialize frame");

// Assert that deserialized header has the original content
let deserialized_header = deserialized_frame
.get_header()
.expect("Frame has no header");
let deserialized_header = deserialized_frame.get_header();
assert_eq!(deserialized_header.msg_type(), MSG_TYPE);
assert_eq!(deserialized_header.ext_type(), EXT_TYPE);

Expand Down
85 changes: 44 additions & 41 deletions sv2/framing-sv2/src/framing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ impl<T, B> From<Sv2Frame<T, B>> for Frame<T, B> {
}
}

/// The body of a [`Sv2Frame`], which is either a deserialized payload or
/// serialized bytes. Exactly one variant is always present, eliminating the
/// need for dual-`Option` fields and impossible-state panic branches.
#[derive(Debug, Clone)]
pub enum FrameBody<T, B> {
/// A deserialized message payload, not yet serialized for transmission.
Payload(T),
/// Serialized bytes (header + payload), received from the wire or
/// previously encoded.
Serialized(B),
}

/// Abstraction for a Sv2 frame.
///
/// Represents a regular Sv2 frame, used for all communication outside of the Noise protocol
Expand All @@ -66,9 +78,7 @@ impl<T, B> From<Sv2Frame<T, B>> for Frame<T, B> {
#[derive(Debug, Clone)]
pub struct Sv2Frame<T, B> {
header: Header,
payload: Option<T>,
// Serialized header + payload
serialized: Option<B>,
body: FrameBody<T, B>,
}

impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
Expand All @@ -78,16 +88,16 @@ impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
/// non serialized frame, it is not so cheap (because it serializes it).
#[inline]
pub fn serialize(self, dst: &mut [u8]) -> Result<(), Error> {
if let Some(mut serialized) = self.serialized {
dst.swap_with_slice(serialized.as_mut());
Ok(())
} else if let Some(payload) = self.payload {
to_writer(self.header, dst).map_err(Error::BinarySv2Error)?;
to_writer(payload, &mut dst[Header::SIZE..]).map_err(Error::BinarySv2Error)?;
Ok(())
} else {
// Sv2Frame always has a payload or a serialized payload
panic!("Impossible state")
match self.body {
FrameBody::Serialized(mut serialized) => {
dst.swap_with_slice(serialized.as_mut());
Ok(())
}
FrameBody::Payload(payload) => {
to_writer(self.header, dst).map_err(Error::BinarySv2Error)?;
to_writer(payload, &mut dst[Header::SIZE..]).map_err(Error::BinarySv2Error)?;
Ok(())
}
}
}

Expand All @@ -100,17 +110,18 @@ impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
/// payload. If the frame has not yet been serialized, this function should never be used (it
/// will panic).
pub fn payload(&mut self) -> &mut [u8] {
if let Some(serialized) = self.serialized.as_mut() {
&mut serialized.as_mut()[Header::SIZE..]
} else {
// panic here is the expected behaviour
panic!("Sv2Frame is not yet serialized.")
match &mut self.body {
FrameBody::Serialized(serialized) => &mut serialized.as_mut()[Header::SIZE..],
FrameBody::Payload(_) => {
// panic here is the expected behaviour
panic!("Sv2Frame is not yet serialized.")
}
}
}

/// [`Sv2Frame`] always returns `Some(self.header)`.
pub fn get_header(&self) -> Option<crate::header::Header> {
Some(self.header)
/// [`Sv2Frame`] always has a header.
pub fn get_header(&self) -> crate::header::Header {
self.header
}

/// Tries to build a [`Sv2Frame`] from raw bytes.
Expand All @@ -137,8 +148,7 @@ impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
let header = Header::from_bytes(bytes.as_mut()).expect("Invalid header");
Self {
header,
payload: None,
serialized: Some(bytes),
body: FrameBody::Serialized(bytes),
}
}

Expand Down Expand Up @@ -172,13 +182,9 @@ impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
/// the length of `self.payload`.
#[inline]
pub fn encoded_length(&self) -> usize {
if let Some(serialized) = self.serialized.as_ref() {
serialized.as_ref().len()
} else if let Some(payload) = self.payload.as_ref() {
payload.get_size() + Header::SIZE
} else {
// Sv2Frame always has a payload or a serialized payload
panic!("Impossible state")
match &self.body {
FrameBody::Serialized(serialized) => serialized.as_ref().len(),
FrameBody::Payload(payload) => payload.get_size() + Header::SIZE,
}
}

Expand All @@ -195,8 +201,7 @@ impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
let len = message.get_size() as u32;
Header::from_len(len, message_type, extension_type).map(|header| Self {
header,
payload: Some(message),
serialized: None,
body: FrameBody::Payload(message),
})
}
}
Expand All @@ -205,14 +210,12 @@ impl<A, B> Sv2Frame<A, B> {
/// Maps a `Sv2Frame<A, B>` to `Sv2Frame<C, B>` by applying `fun`, which is assumed to be a
/// closure that converts `A` to `C`
pub fn map<C>(self, fun: fn(A) -> C) -> Sv2Frame<C, B> {
let serialized = self.serialized;
let header = self.header;
let payload = self.payload.map(fun);
Sv2Frame {
header,
payload,
serialized,
}
let body = match self.body {
FrameBody::Payload(p) => FrameBody::Payload(fun(p)),
FrameBody::Serialized(s) => FrameBody::Serialized(s),
};
Sv2Frame { header, body }
}
}

Expand Down Expand Up @@ -245,8 +248,8 @@ impl HandShakeFrame {

/// Builds a [`HandShakeFrame`] from raw bytes. Nothing is assumed or checked about the
/// correctness of the payload.
pub fn from_bytes(bytes: Slice) -> Result<Self, isize> {
Ok(Self::from_bytes_unchecked(bytes))
pub fn from_bytes(bytes: Slice) -> Self {
Self::from_bytes_unchecked(bytes)
}

#[inline]
Expand Down
Loading