-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add string buffer for stdout and stderr (#316)
* add string buffer for stdout and stderr * handle case where buf can't be written * add comment, rewrite condition to handle overflow * return 0 and fmt * check if strings are frozen before writing + tests * raise and handle errors when a string buffer is frozen * use eq not match * document using frozen strings and encoding * remove parentheses * fix comments * use wasm traps when string is frozen
- Loading branch information
1 parent
8de1e4e
commit 3e9485b
Showing
5 changed files
with
231 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
mod macros; | ||
mod nogvl; | ||
mod output_limited_buffer; | ||
mod static_id; | ||
mod symbol_enum; | ||
mod tmplock; | ||
|
||
pub use nogvl::nogvl; | ||
pub use output_limited_buffer::OutputLimitedBuffer; | ||
pub use static_id::StaticId; | ||
pub use symbol_enum::SymbolEnum; | ||
pub use tmplock::Tmplock; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
use magnus::{ | ||
value::{InnerValue, Opaque, ReprValue}, | ||
RString, Ruby, | ||
}; | ||
use std::io; | ||
use std::io::ErrorKind; | ||
|
||
/// A buffer that limits the number of bytes that can be written to it. | ||
/// If the buffer is full, it will truncate the data. | ||
/// Is used in the buffer implementations of stdout and stderr in `WasiCtx` and `WasiCtxBuilder`. | ||
pub struct OutputLimitedBuffer { | ||
buffer: Opaque<RString>, | ||
/// The maximum number of bytes that can be written to the output stream buffer. | ||
capacity: usize, | ||
} | ||
|
||
impl OutputLimitedBuffer { | ||
#[must_use] | ||
pub fn new(buffer: Opaque<RString>, capacity: usize) -> Self { | ||
Self { buffer, capacity } | ||
} | ||
} | ||
|
||
impl io::Write for OutputLimitedBuffer { | ||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { | ||
// Append a buffer to the string and truncate when hitting the capacity. | ||
// We return the input buffer size regardless of whether we truncated or not to avoid a panic. | ||
let ruby = Ruby::get().unwrap(); | ||
|
||
let mut inner_buffer = self.buffer.get_inner_with(&ruby); | ||
|
||
// Handling frozen case here is necessary because magnus does not check if a string is frozen before writing to it. | ||
let is_frozen = inner_buffer.as_value().is_frozen(); | ||
if is_frozen { | ||
return Err(io::Error::new( | ||
ErrorKind::WriteZero, | ||
"Cannot write to a frozen buffer.", | ||
)); | ||
} | ||
|
||
if buf.is_empty() { | ||
return Ok(0); | ||
} | ||
|
||
if inner_buffer | ||
.len() | ||
.checked_add(buf.len()) | ||
.is_some_and(|val| val < self.capacity) | ||
{ | ||
let amount_written = inner_buffer.write(buf)?; | ||
if amount_written < buf.len() { | ||
return Ok(amount_written); | ||
} | ||
} else { | ||
let portion = self.capacity - inner_buffer.len(); | ||
let amount_written = inner_buffer.write(&buf[0..portion])?; | ||
if amount_written < portion { | ||
return Ok(amount_written); | ||
} | ||
}; | ||
|
||
Ok(buf.len()) | ||
} | ||
|
||
fn flush(&mut self) -> io::Result<()> { | ||
let ruby = Ruby::get().unwrap(); | ||
|
||
self.buffer.get_inner_with(&ruby).flush() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters