Skip to main content

qubit_io/std_io/ext/
write_seek_ext.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! Position-preserving extension operations for seekable standard writers.
10
11use std::io::Result;
12use std::io::Seek;
13use std::io::Write;
14
15mod internal;
16
17/// Extension methods for values that implement both [`Write`] and [`Seek`].
18///
19/// `WriteSeekExt` provides position-preserving write helpers for random-access
20/// output use cases such as patching headers, offsets, and indexes after a
21/// stream has already been written.
22///
23/// # Examples
24/// ```
25/// use qubit_io::std_io::ext::WriteSeekExt;
26/// use std::io::Cursor;
27///
28/// let mut output = Cursor::new(b"abcdef".to_vec());
29/// output.set_position(2);
30///
31/// output.write_all_at_preserving_position(1, b"XY")?;
32///
33/// assert_eq!(output.get_ref(), b"aXYdef");
34/// assert_eq!(output.position(), 2);
35/// # Ok::<(), std::io::Error>(())
36/// ```
37pub trait WriteSeekExt: Write + Seek {
38    /// Writes all bytes at `offset` and restores the original position.
39    ///
40    /// This method seeks to `offset`, delegates to [`Write::write_all`], and
41    /// then restores the position that was current before the call.
42    ///
43    /// # Parameters
44    /// - `offset`: Absolute byte offset from the start of the stream.
45    /// - `buffer`: Bytes to write.
46    ///
47    /// # Returns
48    /// Returns `Ok(())` after all bytes have been written and the original
49    /// stream position has been restored.
50    ///
51    /// # Errors
52    /// Returns an error when reading the current position, seeking to `offset`,
53    /// writing bytes, or restoring the original position fails. If restoration
54    /// fails, the restoration error is returned.
55    fn write_all_at_preserving_position(&mut self, offset: u64, buffer: &[u8]) -> Result<()>;
56}
57
58impl<T> WriteSeekExt for T
59where
60    T: Write + Seek + ?Sized,
61{
62    /// Writes at an absolute offset and restores the original position.
63    ///
64    /// # Parameters
65    /// - `offset`: Absolute byte offset to write at.
66    /// - `buffer`: Bytes to write.
67    ///
68    /// # Returns
69    /// `Ok(())` after all bytes have been written and the position restored.
70    ///
71    /// # Errors
72    /// Returns an error when querying, changing, or restoring the stream
73    /// position, or when writing fails.
74    #[inline(always)]
75    fn write_all_at_preserving_position(&mut self, offset: u64, buffer: &[u8]) -> Result<()> {
76        let mut output = self;
77        internal::write_all_at_preserving_position_impl(&mut output, offset, buffer)
78    }
79}