Skip to content

Commit

Permalink
Use io::Error instead of SendError
Browse files Browse the repository at this point in the history
  • Loading branch information
msk committed May 17, 2024
1 parent e585df2 commit 7d27ea8
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 44 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).

### Removed

- `RecvError` is no longer used. The read functions return `std::io::Error`
instead.
- `RecvError` and `SendError` are no longer used. The recv/send functions return
`std::io::Error` instead.
- Bump dependencies.
- Update quinn to version 0.11.
- Update rustls to version 0.23.
Expand Down
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ num_enum = "0.7"
quinn = "0.11"
quinn-proto = "0.11"
serde = { version = "1", features = ["derive"] }
thiserror = "1"
tokio = "1"

[dev-dependencies]
Expand Down
29 changes: 10 additions & 19 deletions src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use bincode::Options;
use quinn::{RecvStream, SendStream};
use serde::{Deserialize, Serialize};
use std::{io, mem};
use thiserror::Error;

/// Receives and deserializes a message with a big-endian 4-byte length header.
///
Expand Down Expand Up @@ -132,32 +131,24 @@ fn from_transport_error_to_io_error(e: quinn_proto::TransportError) -> io::Error
}
}

/// The error type for sending a message as a frame.
#[derive(Debug, Error)]
pub enum SendError {
#[error("message is too large")]
MessageTooLarge,
#[error("failed to write to a stream")]
WriteError(#[from] quinn::WriteError),
}

/// Sends a message as a stream of bytes with a big-endian 4-byte length header.
///
/// `buf` will be cleared after the message is sent.
///
/// # Errors
///
/// * `SendError::MessageTooLarge`: if the message is too large
/// * `SendError::WriteError`: if the message could not be written
pub async fn send<T>(send: &mut SendStream, buf: &mut Vec<u8>, msg: T) -> Result<(), SendError>
/// Returns [`std::io::ErrorKind::InvalidData`] if the message is too large, or
/// other errors if the message could not be written to the stream.
pub async fn send<T>(send: &mut SendStream, buf: &mut Vec<u8>, msg: T) -> io::Result<()>
where
T: Serialize,
{
buf.resize(mem::size_of::<u32>(), 0);
bincode::DefaultOptions::new()
.serialize_into(&mut *buf, &msg)
.map_err(|_| SendError::MessageTooLarge)?;
let len = u32::try_from(buf.len() - 4).map_err(|_| SendError::MessageTooLarge)?;
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let len =
u32::try_from(buf.len() - 4).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
buf[..mem::size_of::<u32>()].clone_from_slice(&len.to_be_bytes());
send.write_all(buf).await?;
buf.clear();
Expand All @@ -168,10 +159,10 @@ where
///
/// # Errors
///
/// * `SendError::MessageTooLarge`: if the message is too large
/// * `SendError::WriteError`: if the message could not be written
pub async fn send_raw(send: &mut SendStream, buf: &[u8]) -> Result<(), SendError> {
let len = u32::try_from(buf.len()).map_err(|_| SendError::MessageTooLarge)?;
/// Returns an error if the message is too large or could not be written.
pub async fn send_raw(send: &mut SendStream, buf: &[u8]) -> io::Result<()> {
let len =
u32::try_from(buf.len()).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
send.write_all(&len.to_be_bytes()).await?;
send.write_all(buf).await?;
Ok(())
Expand Down
28 changes: 13 additions & 15 deletions src/message.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Functions and errors for handling messages.

use crate::frame::{self, SendError};
use crate::frame;
use bincode::Options;
use quinn::{RecvStream, SendStream};
use serde::Serialize;
Expand Down Expand Up @@ -39,14 +39,14 @@ pub async fn recv_request_raw<'b>(
///
/// # Errors
///
/// * `SendError::MessageTooLarge` if the message is too long to be serialized
/// * `SendError::WriteError` if the message could not be written
/// Returns [`std::io::ErrorKind::InvalidData`] if the message is too large, or
/// other errors if the message could not be written to the stream.
pub async fn send_request<C, B>(
send: &mut SendStream,
buf: &mut Vec<u8>,
code: C,
body: B,
) -> Result<(), SendError>
) -> io::Result<()>
where
C: Into<u32>,
B: Serialize,
Expand All @@ -57,7 +57,7 @@ where
buf.extend_from_slice(&code.into().to_le_bytes());
bincode::DefaultOptions::new()
.serialize_into(buf as &mut dyn Write, &body)
.map_err(|_| SendError::MessageTooLarge)?;
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
frame::send_raw(send, buf).await?;
buf.clear();
Ok(())
Expand All @@ -69,15 +69,14 @@ where
///
/// # Errors
///
/// * `SendError::MessageTooLarge` if `body` is too large to be serialized
/// * `SendError::WriteError` if the message could not be written
/// Returns [`std::io::ErrorKind::InvalidData`] if the message is too large, or
/// other errors if the message could not be written to the stream.
pub async fn send_ok<T: Serialize>(
send: &mut SendStream,
buf: &mut Vec<u8>,
body: T,
) -> Result<(), SendError> {
frame::send(send, buf, Ok(body) as Result<T, &str>).await?;
Ok(())
) -> io::Result<()> {
frame::send(send, buf, Ok(body) as Result<T, &str>).await
}

/// Sends an `Err` response.
Expand All @@ -86,15 +85,14 @@ pub async fn send_ok<T: Serialize>(
///
/// # Errors
///
/// * `SendError::MessageTooLarge` if `e` is too large to be serialized
/// * `SendError::WriteError` if the message could not be written
/// Returns [`std::io::ErrorKind::InvalidData`] if the message is too large, or
/// other errors if the message could not be written to the stream.
pub async fn send_err<E: fmt::Display>(
send: &mut SendStream,
buf: &mut Vec<u8>,
e: E,
) -> Result<(), SendError> {
frame::send(send, buf, Err(format!("{e:#}")) as Result<(), String>).await?;
Ok(())
) -> io::Result<()> {
frame::send(send, buf, Err(format!("{e:#}")) as Result<(), String>).await
}

#[cfg(test)]
Expand Down
18 changes: 11 additions & 7 deletions src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,20 @@ pub fn parse_args<'de, T: Deserialize<'de>>(args: &'de [u8]) -> io::Result<T> {
///
/// # Errors
///
/// * `SendError::MessageTooLarge` if `e` is too large to be serialized
/// * `SendError::WriteError` if the message could not be written
/// Returns [`std::io::ErrorKind::InvalidData`] if the message is too large, or
/// other errors if the message could not be written to the stream.
pub async fn send_response<T: Serialize>(
send: &mut SendStream,
buf: &mut Vec<u8>,
body: T,
) -> Result<(), frame::SendError> {
match frame::send(send, buf, body).await {
Ok(()) => Ok(()),
Err(frame::SendError::WriteError(e)) => Err(frame::SendError::WriteError(e)),
Err(e) => message::send_err(send, buf, e).await,
) -> io::Result<()> {
if let Err(e) = frame::send(send, buf, body).await {
if e.kind() == io::ErrorKind::InvalidData {
message::send_err(send, buf, e).await

Check warning on line 39 in src/request.rs

View check run for this annotation

Codecov / codecov/patch

src/request.rs#L36-L39

Added lines #L36 - L39 were not covered by tests
} else {
Err(e)

Check warning on line 41 in src/request.rs

View check run for this annotation

Codecov / codecov/patch

src/request.rs#L41

Added line #L41 was not covered by tests
}
} else {
Ok(())

Check warning on line 44 in src/request.rs

View check run for this annotation

Codecov / codecov/patch

src/request.rs#L44

Added line #L44 was not covered by tests
}
}

0 comments on commit 7d27ea8

Please sign in to comment.