Skip to content

Commit

Permalink
ChunkWriter has a write_fmt method, allowing it to be using in th…
Browse files Browse the repository at this point in the history
…e `write` macro
  • Loading branch information
sammhicks committed Jul 2, 2024
1 parent 8033a31 commit f66c158
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
5 changes: 4 additions & 1 deletion src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ pub trait WriteExt: Write {
loop {
match FormatBuffer::new(ignore_count).write(args) {
Ok(data) => return self.write_all(data).await,
Err(FormatBufferWriteError::FormatError) => return Ok(()),
Err(FormatBufferWriteError::FormatError) => {
log_warn!("Skipping writing due to Format Error");
return Ok(());
}
Err(FormatBufferWriteError::OutOfSpace(data)) => {
self.write_all(data).await?;
ignore_count += data.len();
Expand Down
10 changes: 5 additions & 5 deletions src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ pub use sse::EventStream;
pub use status::StatusCode;
pub use ws::WebSocketUpgrade;

struct MeasureFormatSize(pub usize);
struct MeasureFormatSize<'a>(&'a mut usize);

impl fmt::Write for MeasureFormatSize {
impl<'a> fmt::Write for MeasureFormatSize<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0 += s.len();
*self.0 += s.len();

Ok(())
}
Expand Down Expand Up @@ -360,8 +360,8 @@ impl<'a> Content for fmt::Arguments<'a> {

fn content_length(&self) -> usize {
use fmt::Write;
let mut size = MeasureFormatSize(0);
write!(&mut size, "{self}").map_or(0, |()| size.0)
let mut size = 0;
write!(MeasureFormatSize(&mut size), "{self}").map_or(0, |()| size)
}

async fn write_content<R: Read, W: Write>(
Expand Down
33 changes: 29 additions & 4 deletions src/response/chunked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub struct ChunkWriter<W: crate::io::Write> {
}

impl<W: crate::io::Write> ChunkWriter<W> {
/// Write a chunk to the client
/// Write a chunk to the client.
pub async fn write_chunk(&mut self, chunk: &[u8]) -> Result<(), W::Error> {
use crate::io::WriteExt;

Expand All @@ -25,12 +25,37 @@ impl<W: crate::io::Write> ChunkWriter<W> {
self.writer.flush().await
}

/// Finish writing chunks
/// Finish writing chunks.
pub async fn finalize(mut self) -> Result<ChunksWritten, W::Error> {
self.writer.write_all(b"0\r\n\r\n").await?;
self.writer.flush().await?;

Ok(ChunksWritten(()))
}

/// Write formatted text as a single chunk. This is typically called using the `write!` macro.
pub async fn write_fmt(&mut self, args: core::fmt::Arguments<'_>) -> Result<(), W::Error> {
use crate::io::WriteExt;
use core::fmt::Write;

let mut chunk_size = 0;

if super::MeasureFormatSize(&mut chunk_size)
.write_fmt(args)
.is_err()
{
log_warn!("Skipping writing chunk due to Format Error");

return Ok(());
}

if chunk_size == 0 {
return Ok(());
}

write!(&mut self.writer, "{chunk_size:x}\r\n{args}\r\n",).await?;
self.writer.flush().await
}
}

/// A series of chunks forming the response body
Expand Down Expand Up @@ -64,8 +89,8 @@ impl<C: Chunks> ChunkedResponse<C> {

impl<C: Chunks> super::Body for Body<C> {
async fn write_response_body<
R: embedded_io_async::Read,
W: embedded_io_async::Write<Error = R::Error>,
R: crate::io::Read,
W: crate::io::Write<Error = R::Error>,
>(
self,
_connection: super::Connection<'_, R>,
Expand Down
8 changes: 5 additions & 3 deletions src/response/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,10 +481,12 @@ impl<T: serde::Serialize> super::Content for JsonBody<T> {
match &self.0 {
JsonStream::Short { buffer } => buffer.data.len(),
JsonStream::Long { buffer: _, value } => {
let mut content_length = super::MeasureFormatSize(0);
let mut content_length = 0;
value
.serialize(Serializer(&mut content_length))
.map_or(0, |()| content_length.0)
.serialize(Serializer(&mut super::MeasureFormatSize(
&mut content_length,
)))
.map_or(0, |()| content_length)
}
}
}
Expand Down

0 comments on commit f66c158

Please sign in to comment.