qubit_io/ext/write_ext.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10
11use std::io::{
12 Result,
13 Write,
14};
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 unsafe fn write_unchecked(&mut self, buffer: &[u8], start_index: usize, count: usize) -> Result<usize> {
47 debug_assert!(
48 start_index
49 .checked_add(count)
50 .is_some_and(|end_index| end_index <= buffer.len()),
51 "unchecked write range exceeds buffer"
52 );
53 // SAFETY: The caller guarantees that the computed pointer and length
54 // form a valid subslice of `buffer`.
55 let source = unsafe { core::slice::from_raw_parts(buffer.as_ptr().add(start_index), count) };
56 self.write(source)
57 }
58
59 /// Writes exactly `count` bytes from a range of `buffer` without checking
60 /// the range bounds in release builds.
61 ///
62 /// This method delegates to [`Write::write_all`] after creating the source
63 /// slice with raw pointer arithmetic. It keeps the same short-write,
64 /// [`std::io::ErrorKind::Interrupted`], and [`std::io::ErrorKind::WriteZero`]
65 /// behavior as [`Write::write_all`].
66 ///
67 /// # Parameters
68 /// - `buffer`: Source buffer.
69 /// - `start_index`: Start offset inside `buffer`.
70 /// - `count`: Number of bytes to write.
71 ///
72 /// # Errors
73 /// Returns the error reported by [`Write::write_all`].
74 ///
75 /// # Safety
76 /// The caller must guarantee that `start_index..start_index + count` is a
77 /// valid range within `buffer` and that `start_index + count` does not
78 /// overflow `usize`.
79 unsafe fn write_all_unchecked(&mut self, buffer: &[u8], start_index: usize, count: usize) -> Result<()> {
80 debug_assert!(
81 start_index
82 .checked_add(count)
83 .is_some_and(|end_index| end_index <= buffer.len()),
84 "unchecked write range exceeds buffer"
85 );
86 // SAFETY: The caller guarantees that the computed pointer and length
87 // form a valid subslice of `buffer`.
88 let source = unsafe { core::slice::from_raw_parts(buffer.as_ptr().add(start_index), count) };
89 self.write_all(source)
90 }
91}
92
93impl<T> WriteExt for T where T: Write + ?Sized {}