Skip to content

Commit

Permalink
Change CloseFrame to use Utf8Bytes for reason
Browse files Browse the repository at this point in the history
  • Loading branch information
alexheretic committed Dec 17, 2024
1 parent 4cad6a7 commit 46d681e
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 35 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Unreleased
- Implement `AsRef<[u8]>` for `Payload`, `AsRef<[u8]>`, `AsRef<str>` for `Utf8Payload`.
- Implement `&str`-like `PartialEq` for `Utf8Payload`.
- Simplify `Message` to use `Bytes` payload directly with simpler `Utf8Bytes` for text.
- Change `CloseFrame` to use `Utf8Bytes` for `reason`.

# 0.25.0

Expand Down
31 changes: 10 additions & 21 deletions src/protocol/frame/frame.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use byteorder::{NetworkEndian, ReadBytesExt};
use log::*;
use std::{
borrow::Cow,
default::Default,
fmt,
io::{Cursor, ErrorKind, Read, Write},
Expand All @@ -9,9 +10,6 @@ use std::{
string::String,
};

use byteorder::{NetworkEndian, ReadBytesExt};
use log::*;

use super::{
coding::{CloseCode, Control, Data, OpCode},
mask::{apply_mask, generate_mask},
Expand All @@ -20,25 +18,18 @@ use crate::{
error::{Error, ProtocolError, Result},
protocol::frame::Utf8Bytes,
};
use bytes::{Buf, Bytes, BytesMut};
use bytes::{Bytes, BytesMut};

/// A struct representing the close command.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CloseFrame<'t> {
pub struct CloseFrame {
/// The reason as a code.
pub code: CloseCode,
/// The reason as text string.
pub reason: Cow<'t, str>,
}

impl CloseFrame<'_> {
/// Convert into a owned string.
pub fn into_owned(self) -> CloseFrame<'static> {
CloseFrame { code: self.code, reason: self.reason.into_owned().into() }
}
pub reason: Utf8Bytes,
}

impl fmt::Display for CloseFrame<'_> {
impl fmt::Display for CloseFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} ({})", self.reason, self.code)
}
Expand Down Expand Up @@ -284,16 +275,14 @@ impl Frame {

/// Consume the frame into a closing frame.
#[inline]
pub(crate) fn into_close(self) -> Result<Option<CloseFrame<'static>>> {
pub(crate) fn into_close(self) -> Result<Option<CloseFrame>> {
match self.payload.len() {
0 => Ok(None),
1 => Err(Error::Protocol(ProtocolError::InvalidCloseSequence)),
_ => {
let mut data = BytesMut::from(self.payload);
let code = u16::from_be_bytes([data[0], data[1]]).into();
data.advance(2);
let text = String::from_utf8(data.to_vec())?;
Ok(Some(CloseFrame { code, reason: text.into() }))
let code = u16::from_be_bytes([self.payload[0], self.payload[1]]).into();
let reason = Utf8Bytes::try_from(self.payload.slice(2..))?;
Ok(Some(CloseFrame { code, reason }))
}
}
}
Expand Down
16 changes: 5 additions & 11 deletions src/protocol/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
error::{CapacityError, Error, Result},
protocol::frame::Utf8Bytes,
};
use std::{borrow::Cow, fmt, result::Result as StdResult, str};
use std::{fmt, result::Result as StdResult, str};

mod string_collect {
use utf8::DecodeError;
Expand Down Expand Up @@ -169,7 +169,7 @@ pub enum Message {
/// The payload here must have a length less than 125 bytes
Pong(Bytes),
/// A close message with the optional close frame.
Close(Option<CloseFrame<'static>>),
Close(Option<CloseFrame>),
/// Raw frame. Note, that you're not going to get this value while reading the message.
Frame(Frame),
}
Expand Down Expand Up @@ -237,13 +237,10 @@ impl Message {
/// Consume the WebSocket and return it as binary data.
pub fn into_data(self) -> Bytes {
match self {
Message::Text(string) => string.into(),
Message::Text(utf8) => utf8.into(),
Message::Binary(data) | Message::Ping(data) | Message::Pong(data) => data,
Message::Close(None) => <_>::default(),
Message::Close(Some(frame)) => match frame.reason {
Cow::Borrowed(s) => Bytes::from_static(s.as_bytes()),
Cow::Owned(s) => s.into(),
},
Message::Close(Some(frame)) => frame.reason.into(),
Message::Frame(frame) => frame.into_payload(),
}
}
Expand All @@ -256,10 +253,7 @@ impl Message {
Ok(data.try_into()?)
}
Message::Close(None) => Ok(<_>::default()),
Message::Close(Some(frame)) => Ok(match frame.reason {
Cow::Borrowed(s) => Utf8Bytes::from_static(s),
Cow::Owned(s) => s.into(),
}),
Message::Close(Some(frame)) => Ok(frame.reason),
Message::Frame(frame) => Ok(frame.into_text()?),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ impl WebSocketContext {

/// Received a close frame. Tells if we need to return a close frame to the user.
#[allow(clippy::option_option)]
fn do_close<'t>(&mut self, close: Option<CloseFrame<'t>>) -> Option<Option<CloseFrame<'t>>> {
fn do_close(&mut self, close: Option<CloseFrame>) -> Option<Option<CloseFrame>> {
debug!("Received close frame: {close:?}");
match self.state {
WebSocketState::Active => {
Expand Down

0 comments on commit 46d681e

Please sign in to comment.