qubit_io/buffered/buffered_output.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 Error,
11 ErrorKind,
12 Result,
13 Seek,
14 SeekFrom,
15 Write,
16};
17
18use crate::buffered::DEFAULT_BUFFER_CAPACITY;
19use crate::{
20 Buffer,
21 Output,
22};
23
24/// Buffered unit output over a wrapped output sink.
25///
26/// This type keeps a fixed-size unit buffer in front of an underlying output so
27/// small unit writes can be accumulated before they are written to the I/O
28/// target. Large writes may bypass the buffer after pending buffered units
29/// have been flushed.
30///
31/// `BufferedOutput` is deliberately unit-oriented. It performs no binary
32/// encoding, text encoding, or record framing. Higher-level writers can either
33/// use the standard [`Write`] implementation or write directly into
34/// [`Self::spare_buffer_mut`] or [`Self::spare_raw_parts_mut`] and then call
35/// [`Self::advance`] or [`Self::advance_unchecked`] after validating the range
36/// they initialized. Callers that need to recover the wrapped writer should
37/// call [`Write::flush`] first, then use [`Self::into_parts`].
38#[derive(Debug)]
39pub struct BufferedOutput<O>
40where
41 O: Output,
42 O::Item: Copy + Default,
43{
44 inner: O,
45 buffer: Buffer<O::Item>,
46}
47
48impl<O> BufferedOutput<O>
49where
50 O: Output,
51 O::Item: Copy + Default,
52{
53 /// Creates a buffered unit output with the default capacity.
54 ///
55 /// # Parameters
56 ///
57 /// * `inner` - The output that receives units when the internal buffer is
58 /// flushed.
59 ///
60 /// # Returns
61 ///
62 /// A new buffered unit output using `DEFAULT_BUFFER_CAPACITY`.
63 #[inline(always)]
64 #[must_use]
65 pub fn new(inner: O) -> Self {
66 Self::with_capacity(inner, DEFAULT_BUFFER_CAPACITY)
67 }
68
69 /// Creates a buffered unit output with at least the requested capacity.
70 ///
71 /// # Parameters
72 ///
73 /// * `inner` - The output that receives units when the internal buffer is
74 /// flushed.
75 /// * `capacity` - The requested internal buffer capacity in units.
76 ///
77 /// # Returns
78 ///
79 /// A new buffered unit output whose actual buffer capacity is
80 /// `capacity.max(1)`.
81 #[inline(always)]
82 #[must_use]
83 pub fn with_capacity(inner: O, capacity: usize) -> Self {
84 Self {
85 inner,
86 buffer: Buffer::with_capacity(capacity),
87 }
88 }
89
90 /// Returns a shared reference to the wrapped writer.
91 ///
92 /// # Returns
93 ///
94 /// An immutable reference to the underlying writer. Pending bytes may
95 /// still be present in the internal buffer and are not flushed by this
96 /// method.
97 #[inline(always)]
98 pub const fn inner(&self) -> &O {
99 &self.inner
100 }
101
102 /// Returns an exclusive reference to the wrapped writer.
103 ///
104 /// Pending bytes may still be present in the internal buffer and are not
105 /// flushed by this method.
106 ///
107 /// # Returns
108 ///
109 /// A mutable reference to the underlying writer.
110 #[inline(always)]
111 pub fn inner_mut(&mut self) -> &mut O {
112 &mut self.inner
113 }
114
115 /// Returns the internal buffer capacity.
116 ///
117 /// # Returns
118 ///
119 /// The total number of units that can be held by the internal buffer.
120 #[inline(always)]
121 #[must_use]
122 pub fn capacity(&self) -> usize {
123 self.buffer.capacity()
124 }
125
126 /// Returns the unused capacity in the internal buffer.
127 ///
128 /// # Returns
129 ///
130 /// The number of bytes that can still be appended to the internal buffer
131 /// before it must be flushed.
132 #[inline(always)]
133 #[must_use]
134 pub fn spare_capacity(&self) -> usize {
135 self.buffer.spare_capacity()
136 }
137
138 /// Returns the unused portion of the internal buffer.
139 ///
140 /// Callers may write initialized bytes into the returned slice and then
141 /// call [`Self::advance`] with the number of bytes written.
142 ///
143 /// # Returns
144 ///
145 /// A mutable slice over the spare buffer capacity.
146 #[inline(always)]
147 #[must_use]
148 pub fn spare_buffer_mut(&mut self) -> &mut [O::Item] {
149 let limit = self.buffer.limit();
150 &mut self.buffer.data_mut()[limit..]
151 }
152
153 /// Returns raw spare-buffer parts for hot-path callers.
154 ///
155 /// The returned slice is the full internal backing storage. `index` is the
156 /// start of the spare byte window, and `count` is the number of spare
157 /// bytes. Callers that need a slice can use `&mut buffer[index..index +
158 /// count]`; callers that already validated bounds can pass `buffer` and
159 /// `index` directly to indexed unchecked codecs.
160 ///
161 /// Mutating bytes outside `index..index + count` changes pending output
162 /// bytes and may corrupt the logical stream.
163 ///
164 /// # Returns
165 ///
166 /// The backing storage, the spare start index, and the spare byte count.
167 #[inline(always)]
168 #[must_use]
169 pub fn spare_raw_parts_mut(&mut self) -> (&mut [O::Item], usize, usize) {
170 let index = self.buffer.limit();
171 let count = self.buffer.spare_capacity();
172 (self.buffer.data_mut(), index, count)
173 }
174
175 /// Marks `count` bytes from [`Self::spare_buffer_mut`] as written.
176 ///
177 /// # Parameters
178 ///
179 /// * `count` - Number of bytes initialized by the caller.
180 ///
181 /// # Panics
182 ///
183 /// Panics when `count` exceeds [`Self::spare_capacity`].
184 #[inline(always)]
185 pub fn advance(&mut self, count: usize) {
186 assert!(
187 count <= self.spare_capacity(),
188 "cannot advance beyond spare output buffer"
189 );
190 // SAFETY: The assertion proves that `count` is within spare capacity.
191 unsafe {
192 self.buffer.advance_unchecked(count);
193 }
194 }
195
196 /// Marks spare bytes as written without checking bounds.
197 ///
198 /// # Parameters
199 ///
200 /// * `count` - Number of initialized spare bytes to make pending for
201 /// output.
202 ///
203 /// # Safety
204 ///
205 /// The caller must guarantee that `count <= self.spare_capacity()` and
206 /// that the corresponding bytes returned by [`Self::spare_buffer_mut`]
207 /// have been initialized.
208 #[inline(always)]
209 pub unsafe fn advance_unchecked(&mut self, count: usize) {
210 // SAFETY: The caller guarantees that `count` is within spare capacity.
211 unsafe {
212 self.buffer.advance_unchecked(count);
213 }
214 }
215
216 /// Writes bytes into the internal buffer without checking spare capacity.
217 ///
218 /// # Parameters
219 ///
220 /// * `input` - The source bytes.
221 /// * `input_index` - The starting index in `input`.
222 /// * `count` - The number of bytes to copy.
223 ///
224 /// # Safety
225 ///
226 /// The caller must ensure that `input_index..input_index + count` is valid
227 /// in `input`, that `count <= self.spare_capacity()`, and that the copied
228 /// source range does not overlap with the destination range in the internal
229 /// buffer.
230 #[inline(always)]
231 unsafe fn write_to_buffer_unchecked(
232 &mut self,
233 input: &[O::Item],
234 input_index: usize,
235 count: usize,
236 ) {
237 // SAFETY: The caller upholds `Buffer::copy_from_unchecked` range and
238 // non-overlap requirements.
239 unsafe {
240 self.buffer.copy_from_unchecked(input, input_index, count);
241 }
242 }
243}
244
245impl<O> BufferedOutput<O>
246where
247 O: Output,
248 O::Item: Copy + Default,
249{
250 /// Consumes this buffered output without flushing pending bytes.
251 ///
252 /// This method performs no I/O. Pending bytes that have been accepted into
253 /// the internal buffer but not written to the wrapped writer are returned
254 /// as the second tuple item.
255 ///
256 /// # Returns
257 ///
258 /// The wrapped writer and pending bytes in logical write order.
259 #[inline(always)]
260 #[must_use]
261 pub fn into_parts(self) -> (O, Vec<O::Item>) {
262 let pending = self.pending_slice().to_vec();
263 (self.inner, pending)
264 }
265
266 /// Ensures that at least `count` bytes are available in the spare buffer.
267 ///
268 /// # Parameters
269 ///
270 /// * `count` - Number of spare bytes required.
271 ///
272 /// # Errors
273 ///
274 /// Returns any non-interrupted I/O error produced while flushing buffered
275 /// bytes. Returns [`ErrorKind::InvalidInput`] if `count` exceeds the buffer
276 /// capacity. Returns [`ErrorKind::InvalidData`] if the wrapped writer
277 /// reports more bytes than the pending buffer range contained.
278 pub fn ensure_spare_capacity(&mut self, count: usize) -> Result<()> {
279 if count > self.buffer.capacity() {
280 return Err(Error::new(
281 ErrorKind::InvalidInput,
282 "requested spare capacity exceeds buffered output capacity",
283 ));
284 }
285 if self.spare_capacity() < count {
286 self.flush_buffer()?;
287 }
288 Ok(())
289 }
290
291 /// Writes all bytes through the internal buffer.
292 ///
293 /// Small inputs are appended to the internal buffer. Inputs that do not
294 /// fit may flush the buffer first, and inputs at least as large as the
295 /// buffer may be written directly to the wrapped writer.
296 ///
297 /// # Parameters
298 ///
299 /// * `input` - The bytes to write.
300 ///
301 /// # Returns
302 ///
303 /// `Ok(())` after all bytes from `input` have been accepted.
304 ///
305 /// # Errors
306 ///
307 /// Returns any I/O error produced while flushing pending bytes or writing a
308 /// large input directly to the wrapped writer. Flush failures include
309 /// [`ErrorKind::WriteZero`] if the writer reports that zero bytes were
310 /// written before the buffer is drained, and [`ErrorKind::InvalidData`] if
311 /// it reports more bytes than the requested range contained.
312 ///
313 /// # Safety
314 ///
315 /// The caller must guarantee that `input_index..input_index + count` is a
316 /// valid range inside `input` and that the addition does not overflow.
317 #[inline]
318 pub unsafe fn write_all_unchecked(
319 &mut self,
320 input: &[O::Item],
321 input_index: usize,
322 count: usize,
323 ) -> Result<()> {
324 debug_assert!(
325 input_index
326 .checked_add(count)
327 .is_some_and(|end| end <= input.len()),
328 "unchecked write range exceeds input buffer"
329 );
330 if count < self.spare_capacity() {
331 // SAFETY: The branch proves that the input fits in spare capacity.
332 unsafe {
333 self.write_to_buffer_unchecked(input, input_index, count);
334 }
335 Ok(())
336 } else {
337 // SAFETY: The caller guarantees the source range is valid.
338 unsafe { self.write_all_cold(input, input_index, count) }
339 }
340 }
341
342 /// Handles slow-path raw writes that must flush or bypass the buffer.
343 ///
344 /// # Parameters
345 ///
346 /// * `input` - The bytes to write after the fast path determined that they
347 /// do not fit comfortably in the current spare buffer capacity.
348 ///
349 /// # Returns
350 ///
351 /// `Ok(())` after all bytes from `input` have been accepted either by the
352 /// buffer or by the wrapped writer.
353 ///
354 /// # Errors
355 ///
356 /// Returns any I/O error produced while flushing pending bytes or writing a
357 /// large input directly to the wrapped writer. Flush failures include
358 /// [`ErrorKind::WriteZero`] if the writer reports that zero bytes were
359 /// written before the buffer is drained, and [`ErrorKind::InvalidData`] if
360 /// it reports more bytes than the requested range contained.
361 #[cold]
362 #[inline(never)]
363 unsafe fn write_all_cold(
364 &mut self,
365 input: &[O::Item],
366 input_index: usize,
367 count: usize,
368 ) -> Result<()> {
369 if count > self.spare_capacity() {
370 self.flush_buffer()?;
371 }
372 if count >= self.buffer.capacity() {
373 // SAFETY: The range covers the full source slice.
374 unsafe { self.write_all_inner_unchecked(input, input_index, count) }
375 } else {
376 // SAFETY: After the optional flush, any input smaller than the
377 // buffer capacity fits in the empty or sufficiently spare buffer.
378 unsafe {
379 self.write_to_buffer_unchecked(input, input_index, count);
380 }
381 Ok(())
382 }
383 }
384
385 /// Handles slow-path raw writes for [`Write::write`] semantics.
386 ///
387 /// The method preserves `Write::write` behavior: it may accept fewer bytes
388 /// than the input length when the write is delegated directly to the
389 /// wrapped writer.
390 ///
391 /// # Parameters
392 ///
393 /// * `input` - The bytes to write after the fast path determined that they
394 /// do not fit comfortably in the current spare buffer capacity.
395 ///
396 /// # Returns
397 ///
398 /// The number of bytes accepted. Buffered writes return `input.len()`;
399 /// direct writes return the byte count reported by the wrapped writer.
400 ///
401 /// # Errors
402 ///
403 /// Returns any I/O error produced while flushing pending bytes or writing a
404 /// large input directly to the wrapped writer. Flush failures include
405 /// [`ErrorKind::WriteZero`] if the writer reports that zero bytes were
406 /// written before the buffer is drained, and [`ErrorKind::InvalidData`] if
407 /// it reports more bytes than the requested range contained.
408 #[cold]
409 #[inline(never)]
410 unsafe fn write_cold(
411 &mut self,
412 input: &[O::Item],
413 input_index: usize,
414 count: usize,
415 ) -> Result<usize> {
416 if count > self.spare_capacity() {
417 self.flush_buffer()?;
418 }
419 if count >= self.buffer.capacity() {
420 // SAFETY: The range covers the full source slice.
421 unsafe { self.write_inner_unchecked(input, input_index, count) }
422 } else {
423 // SAFETY: After the optional flush, any input smaller than the
424 // buffer capacity fits in the empty or sufficiently spare buffer.
425 unsafe {
426 self.write_to_buffer_unchecked(input, input_index, count);
427 }
428 Ok(count)
429 }
430 }
431
432 /// Flushes buffered bytes to the wrapped writer.
433 ///
434 /// The method retries interrupted writes. If an error occurs after some
435 /// bytes have been written, the already-written bytes are removed from the
436 /// front of the buffer and the unwritten suffix is kept for a later retry.
437 ///
438 /// # Returns
439 ///
440 /// `Ok(())` once all currently buffered bytes have been written to the
441 /// wrapped writer.
442 ///
443 /// # Errors
444 ///
445 /// Returns any non-interrupted I/O error produced by the wrapped writer.
446 /// Returns [`ErrorKind::WriteZero`] if the writer reports a zero-length
447 /// write before all buffered bytes are drained. Returns
448 /// [`ErrorKind::InvalidData`] if the writer reports more bytes than the
449 /// pending buffer range contained.
450 pub fn flush_buffer(&mut self) -> Result<()> {
451 while !self.buffer.is_empty() {
452 let position = self.buffer.position();
453 let available = self.buffer.available();
454 // SAFETY: `position..position + available` is the current readable
455 // range maintained by `Buffer`.
456 match unsafe {
457 self.inner.write_unchecked(
458 self.buffer.data(),
459 position,
460 available,
461 )
462 } {
463 Ok(0) => {
464 self.buffer.compact();
465 return Err(Error::new(
466 ErrorKind::WriteZero,
467 "failed to write buffered data",
468 ));
469 }
470 Ok(written) => {
471 if let Err(error) = validate_write_count(written, available)
472 {
473 self.buffer.compact();
474 return Err(error);
475 }
476 // SAFETY: The validated count is in `0..=available`.
477 unsafe {
478 self.buffer.consume_unchecked(written);
479 }
480 }
481 Err(error) if error.kind() == ErrorKind::Interrupted => {}
482 Err(error) => {
483 self.buffer.compact();
484 return Err(error);
485 }
486 }
487 }
488 self.buffer.clear();
489 Ok(())
490 }
491
492 /// Flushes buffered bytes and then flushes the wrapped writer.
493 ///
494 /// # Returns
495 ///
496 /// `Ok(())` once pending buffered bytes have been written and the wrapped
497 /// writer's own flush operation succeeds.
498 ///
499 /// # Errors
500 ///
501 /// Returns any non-interrupted I/O error produced while flushing buffered
502 /// bytes, [`ErrorKind::WriteZero`] if the wrapped writer cannot make
503 /// progress while draining the buffer, [`ErrorKind::InvalidData`] if the
504 /// writer reports an impossible byte count, or any error returned by
505 /// [`Write::flush`] on the wrapped writer.
506 #[inline(always)]
507 fn flush_all(&mut self) -> Result<()> {
508 self.flush_buffer()
509 .and_then(|()| Output::flush(&mut self.inner))
510 }
511
512 /// Flushes buffered units and then flushes the wrapped output.
513 ///
514 /// # Returns
515 ///
516 /// `Ok(())` once pending buffered units and the wrapped output are
517 /// flushed.
518 ///
519 /// # Errors
520 ///
521 /// Returns any error produced while draining buffered units or flushing
522 /// the wrapped output.
523 #[inline(always)]
524 pub fn flush(&mut self) -> Result<()> {
525 self.flush_all()
526 }
527
528 /// Writes bytes from the input slice and reports the accepted byte count.
529 ///
530 /// This is the buffered implementation for [`Write::write`]-style callers.
531 /// Small inputs are appended to the buffer and reported as fully accepted;
532 /// large inputs may be delegated to the wrapped writer after pending bytes
533 /// are flushed.
534 ///
535 /// # Parameters
536 ///
537 /// * `input` - The bytes to write.
538 ///
539 /// # Returns
540 ///
541 /// The number of bytes accepted. Buffered writes return `input.len()`;
542 /// direct writes return the byte count reported by the wrapped writer.
543 ///
544 /// # Errors
545 ///
546 /// Returns any I/O error produced while flushing pending bytes or writing a
547 /// large input directly to the wrapped writer. Flush failures include
548 /// [`ErrorKind::WriteZero`] if the writer reports that zero bytes were
549 /// written before the buffer is drained, and [`ErrorKind::InvalidData`] if
550 /// it reports more bytes than the requested range contained.
551 ///
552 /// # Safety
553 ///
554 /// The caller must guarantee that `input_index..input_index + count` is a
555 /// valid range inside `input` and that the addition does not overflow.
556 #[inline]
557 pub unsafe fn write_from_unchecked(
558 &mut self,
559 input: &[O::Item],
560 input_index: usize,
561 count: usize,
562 ) -> Result<usize> {
563 debug_assert!(
564 input_index
565 .checked_add(count)
566 .is_some_and(|end| end <= input.len()),
567 "unchecked write range exceeds input buffer"
568 );
569 if count < self.spare_capacity() {
570 // SAFETY: The branch proves that the input fits in spare capacity.
571 unsafe {
572 self.write_to_buffer_unchecked(input, input_index, count);
573 }
574 Ok(count)
575 } else {
576 // SAFETY: The caller guarantees the source range is valid.
577 unsafe { self.write_cold(input, input_index, count) }
578 }
579 }
580
581 /// Flushes pending bytes before seeking the wrapped writer.
582 ///
583 /// # Parameters
584 ///
585 /// * `position` - The target seek position passed to the wrapped writer.
586 ///
587 /// # Returns
588 ///
589 /// The new stream position reported by the wrapped writer.
590 ///
591 /// # Errors
592 ///
593 /// Returns any non-interrupted I/O error produced while flushing buffered
594 /// bytes, [`ErrorKind::WriteZero`] if the wrapped writer cannot make
595 /// progress while draining the buffer, [`ErrorKind::InvalidData`] if the
596 /// writer reports an impossible byte count, or any error returned by
597 /// [`Seek::seek`] on the wrapped writer.
598 #[inline(always)]
599 fn flush_then_seek(&mut self, position: SeekFrom) -> Result<u64>
600 where
601 O: Seek,
602 {
603 self.flush_buffer().and_then(|()| self.inner.seek(position))
604 }
605
606 /// Returns pending bytes currently stored in the internal buffer.
607 ///
608 /// # Returns
609 ///
610 /// A slice over bytes accepted by this output but not yet written to the
611 /// wrapped writer.
612 #[inline(always)]
613 fn pending_slice(&self) -> &[O::Item] {
614 &self.buffer.data()[self.buffer.position()..self.buffer.limit()]
615 }
616
617 /// Writes bytes to the wrapped writer and validates the reported count.
618 ///
619 /// # Parameters
620 ///
621 /// * `input` - Source storage.
622 /// * `input_index` - Start index inside `input`.
623 /// * `count` - Maximum number of bytes to write.
624 ///
625 /// # Returns
626 ///
627 /// The number of bytes accepted by the wrapped writer.
628 ///
629 /// # Errors
630 ///
631 /// Returns the wrapped writer's I/O error, or [`ErrorKind::InvalidData`]
632 /// if it reports a byte count larger than `count`.
633 ///
634 /// # Safety
635 ///
636 /// The caller must guarantee that `input_index..input_index + count` is a
637 /// valid range inside `input` and that the addition does not overflow.
638 #[inline(always)]
639 unsafe fn write_inner_unchecked(
640 &mut self,
641 input: &[O::Item],
642 input_index: usize,
643 count: usize,
644 ) -> Result<usize> {
645 // SAFETY: The caller guarantees the source range is valid.
646 let written =
647 unsafe { self.inner.write_unchecked(input, input_index, count) }?;
648 validate_write_count(written, count)?;
649 Ok(written)
650 }
651
652 /// Writes all bytes in an indexed source range to the wrapped writer.
653 ///
654 /// # Parameters
655 ///
656 /// * `input` - Source storage.
657 /// * `input_index` - Start index inside `input`.
658 /// * `count` - Number of bytes to write.
659 ///
660 /// # Errors
661 ///
662 /// Returns the wrapped writer's I/O error, [`ErrorKind::WriteZero`] if the
663 /// writer cannot make progress, or [`ErrorKind::InvalidData`] if it
664 /// reports an impossible byte count.
665 ///
666 /// # Safety
667 ///
668 /// The caller must guarantee that `input_index..input_index + count` is a
669 /// valid range inside `input` and that the addition does not overflow.
670 unsafe fn write_all_inner_unchecked(
671 &mut self,
672 input: &[O::Item],
673 input_index: usize,
674 count: usize,
675 ) -> Result<()> {
676 let mut written = 0;
677 while written < count {
678 let remaining = count - written;
679 // SAFETY: `written < count`, so this suffix remains inside the
680 // caller-validated source range.
681 match unsafe {
682 self.write_inner_unchecked(
683 input,
684 input_index + written,
685 remaining,
686 )
687 } {
688 Ok(0) => {
689 return Err(Error::new(
690 ErrorKind::WriteZero,
691 "failed to write whole buffer",
692 ));
693 }
694 Ok(count) => written += count,
695 Err(error) if error.kind() == ErrorKind::Interrupted => {}
696 Err(error) => return Err(error),
697 }
698 }
699 Ok(())
700 }
701}
702
703impl<O> Write for BufferedOutput<O>
704where
705 O: Output<Item = u8>,
706{
707 /// Writes bytes through the internal buffer.
708 #[inline(always)]
709 fn write(&mut self, buffer: &[u8]) -> Result<usize> {
710 // SAFETY: The full input slice is a valid source range.
711 unsafe { self.write_from_unchecked(buffer, 0, buffer.len()) }
712 }
713
714 /// Writes all bytes through the internal buffer.
715 #[inline(always)]
716 fn write_all(&mut self, buffer: &[u8]) -> Result<()> {
717 // SAFETY: The full input slice is a valid source range.
718 unsafe { self.write_all_unchecked(buffer, 0, buffer.len()) }
719 }
720
721 /// Flushes the internal buffer and then the wrapped writer.
722 #[inline(always)]
723 fn flush(&mut self) -> Result<()> {
724 self.flush_all()
725 }
726}
727
728impl<O> Seek for BufferedOutput<O>
729where
730 O: Output<Item = u8> + Seek,
731{
732 /// Flushes pending bytes before seeking the wrapped writer.
733 #[inline(always)]
734 fn seek(&mut self, position: SeekFrom) -> Result<u64> {
735 self.flush_then_seek(position)
736 }
737}
738
739/// Validates a byte count returned by a wrapped writer.
740///
741/// # Parameters
742///
743/// * `written` - Byte count reported by the wrapped writer.
744/// * `requested` - Maximum byte count requested from the wrapped writer.
745///
746/// # Errors
747///
748/// Returns [`ErrorKind::InvalidData`] when the wrapped writer reports more
749/// bytes than the source range contained.
750#[inline(always)]
751fn validate_write_count(written: usize, requested: usize) -> Result<()> {
752 if written > requested {
753 return Err(Error::new(
754 ErrorKind::InvalidData,
755 format!(
756 "writer reported {written} bytes for a {requested}-byte buffer"
757 ),
758 ));
759 }
760 Ok(())
761}