Skip to main content

qubit_io/ext/
write_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
9use std::io::{
10    Result,
11    Write,
12};
13
14use crate::util::UncheckedSlice;
15
16/// Extension methods for [`Write`] values.
17///
18/// `WriteExt` provides small method-style helpers for byte writers. The
19/// methods are implemented for every type that implements [`Write`], including
20/// `dyn Write` trait objects.
21pub trait WriteExt: Write {
22    /// Writes bytes from a range of `buffer` without checking the range bounds
23    /// in release builds.
24    ///
25    /// This method delegates to [`Write::write`] after creating the source
26    /// slice with raw pointer arithmetic. It performs at most one write
27    /// operation and returns the number of bytes written, keeping the same
28    /// short-write and error behavior as [`Write::write`].
29    ///
30    /// # Parameters
31    /// - `buffer`: Source buffer.
32    /// - `start_index`: Start offset inside `buffer`.
33    /// - `count`: Maximum number of bytes to write.
34    ///
35    /// # Returns
36    /// The number of bytes written from `buffer[start_index..start_index +
37    /// count]`. The value is in `0..=count`.
38    ///
39    /// # Errors
40    /// Returns the error reported by [`Write::write`].
41    ///
42    /// # Safety
43    /// The caller must guarantee that `start_index..start_index + count` is a
44    /// valid range within `buffer` and that `start_index + count` does not
45    /// overflow `usize`.
46    #[inline(always)]
47    unsafe fn write_unchecked(
48        &mut self,
49        buffer: &[u8],
50        start_index: usize,
51        count: usize,
52    ) -> Result<usize> {
53        debug_assert!(
54            UncheckedSlice::range_fits(buffer.len(), start_index, count),
55            "unchecked write range exceeds buffer"
56        );
57        // SAFETY: The caller guarantees that the computed pointer and length
58        // form a valid subslice of `buffer`.
59        let source =
60            unsafe { UncheckedSlice::subslice(buffer, start_index, count) };
61        self.write(source)
62    }
63
64    /// Writes exactly `count` bytes from a range of `buffer` without checking
65    /// the range bounds in release builds.
66    ///
67    /// This method delegates to [`Write::write_all`] after creating the source
68    /// slice with raw pointer arithmetic. It keeps the same short-write,
69    /// [`std::io::ErrorKind::Interrupted`], and
70    /// [`std::io::ErrorKind::WriteZero`] behavior as [`Write::write_all`].
71    ///
72    /// # Parameters
73    /// - `buffer`: Source buffer.
74    /// - `start_index`: Start offset inside `buffer`.
75    /// - `count`: Number of bytes to write.
76    ///
77    /// # Errors
78    /// Returns the error reported by [`Write::write_all`].
79    ///
80    /// # Safety
81    /// The caller must guarantee that `start_index..start_index + count` is a
82    /// valid range within `buffer` and that `start_index + count` does not
83    /// overflow `usize`.
84    #[inline(always)]
85    unsafe fn write_all_unchecked(
86        &mut self,
87        buffer: &[u8],
88        start_index: usize,
89        count: usize,
90    ) -> Result<()> {
91        debug_assert!(
92            UncheckedSlice::range_fits(buffer.len(), start_index, count),
93            "unchecked write range exceeds buffer"
94        );
95        // SAFETY: The caller guarantees that the computed pointer and length
96        // form a valid subslice of `buffer`.
97        let source =
98            unsafe { UncheckedSlice::subslice(buffer, start_index, count) };
99        self.write_all(source)
100    }
101}
102
103impl<T> WriteExt for T where T: Write + ?Sized {}