Skip to content

Commit d3b238a

Browse files
committed
refactor: zero-copy zen output buffer — replace write_output_bytes with from_output_vec
add_output_buffer_from_vec moves the Vec<u8> directly into the IoProxy WriteVec cursor instead of copying via write_all. write_output_bytes deleted.
1 parent 36aea46 commit d3b238a

File tree

4 files changed

+14
-35
lines changed

4 files changed

+14
-35
lines changed

imageflow_core/src/codecs/mod.rs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -423,29 +423,4 @@ impl CodecInstanceContainer {
423423
)),
424424
}
425425
}
426-
427-
/// Write encoded bytes to the output buffer (for zen pipeline).
428-
///
429-
/// Replaces the output IoProxy with one backed by the given bytes.
430-
/// The buffer then works with `take_output_buffer()` and
431-
/// `output_buffer_raw_parts()` as if an encoder had written it.
432-
/// Write encoded bytes into the output buffer (for zen pipeline).
433-
///
434-
/// The buffer must be in `Ready` state (freshly created via `add_output_buffer`).
435-
/// After writing, `take_output_buffer()` and `output_buffer_raw_parts()` work
436-
/// as if an encoder had written the bytes.
437-
pub fn write_output_bytes(&mut self, bytes: &[u8]) -> Result<()> {
438-
match &mut self.output_state {
439-
OutputBufferState::Ready(ref mut io) => {
440-
use std::io::Write;
441-
io.write_all(bytes).map_err(|e| nerror!(ErrorKind::EncodingIoError, "{}", e))?;
442-
Ok(())
443-
}
444-
_ => Err(nerror!(
445-
ErrorKind::InvalidState,
446-
"io_id {} output buffer not in Ready state for write_output_bytes",
447-
self.io_id
448-
)),
449-
}
450-
}
451426
}

imageflow_core/src/context.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,11 @@ impl Context {
614614
self.add_io(io, io_id, IoDirection::Out).map_err(|e| e.at(here!()))
615615
}
616616

617+
pub fn add_output_buffer_from_vec(&mut self, io_id: i32, bytes: Vec<u8>) -> Result<()> {
618+
let io = IoProxy::from_output_vec(self, io_id, bytes).map_err(|e| e.at(here!()))?;
619+
self.add_io(io, io_id, IoDirection::Out).map_err(|e| e.at(here!()))
620+
}
621+
617622
fn swap_dimensions_by_exif(&mut self, io_id: i32, image_info: &mut ImageInfo) -> Result<()> {
618623
let exif_maybe = self
619624
.get_codec(io_id)
@@ -750,9 +755,7 @@ impl Context {
750755
let output =
751756
crate::zen::zen_build(parsed, &self.security, &job_options).map_err(|e| e.at(here!()))?;
752757
for (io_id, bytes) in output.output_buffers {
753-
let _ = self.add_output_buffer(io_id);
754-
let mut codec = self.get_codec(io_id).map_err(|e| e.at(here!()))?;
755-
codec.write_output_bytes(&bytes).map_err(|e| e.at(here!()))?;
758+
self.add_output_buffer_from_vec(io_id, bytes).map_err(|e| e.at(here!()))?;
756759
}
757760
self.store_zen_captured_bitmaps(output.captured_bitmaps)?;
758761
return Ok(output.job_result);
@@ -878,10 +881,7 @@ impl Context {
878881

879882
// Store encoded outputs in Context's output buffer system.
880883
for (io_id, bytes) in output.output_buffers {
881-
// Add output buffer only if not already present (test infra may pre-add it).
882-
let _ = self.add_output_buffer(io_id);
883-
let mut codec = self.get_codec(io_id).map_err(|e| e.at(here!()))?;
884-
codec.write_output_bytes(&bytes).map_err(|e| e.at(here!()))?;
884+
self.add_output_buffer_from_vec(io_id, bytes).map_err(|e| e.at(here!()))?;
885885
}
886886

887887
// Store captured bitmaps as v2 BitmapKeys for test compatibility.

imageflow_core/src/io.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ impl IoProxy {
201201
Ok(IoProxy { path: None, io_id, backend: IoBackend::WriteVec(Cursor::new(Vec::new())) })
202202
}
203203

204+
/// Wrap an already-encoded `Vec<u8>` as an output buffer — zero copy.
205+
pub fn from_output_vec(context: &Context, io_id: i32, bytes: Vec<u8>) -> Result<IoProxy> {
206+
IoProxy::check_io_id(context, io_id)?;
207+
Ok(IoProxy { path: None, io_id, backend: IoBackend::WriteVec(Cursor::new(bytes)) })
208+
}
209+
204210
pub fn read_vec(context: &Context, io_id: i32, bytes: Vec<u8>) -> Result<IoProxy> {
205211
IoProxy::check_io_id(context, io_id)?;
206212

imageflow_core/src/json/endpoints/v1.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -894,9 +894,7 @@ fn zen_build(context: &mut Context, parsed: Build001) -> Result<BuildV1Response>
894894

895895
// Store encoded output in Context so take_output_buffer() works for C ABI.
896896
for (io_id, bytes) in output.output_buffers {
897-
context.add_output_buffer(io_id).map_err(|e| e.at(here!()))?;
898-
let mut codec = context.get_codec(io_id).map_err(|e| e.at(here!()))?;
899-
codec.write_output_bytes(&bytes).map_err(|e| e.at(here!()))?;
897+
context.add_output_buffer_from_vec(io_id, bytes).map_err(|e| e.at(here!()))?;
900898
}
901899

902900
Ok(BuildV1Response { job_result: output.job_result })

0 commit comments

Comments
 (0)