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