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 {}