oct 0.26.0

Octonary transcodings.
Documentation
// Copyright 2024-2025 Gabriel Bjørnager Jensen.
//
// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of
// the MPL was not distributed with this file, you
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.

//! The [`copy`] function.

mod test;

use crate::io::{DEFAULT_BUF_SIZE, Read, Result, Write};

/// Copies the remainder of a reader into a writer.
///
/// The standard [`std::io::copy`] should always be
/// preferred to this -- when available -- as it is
/// has optimised code paths for hosted
/// environments.
///
#[cfg_attr(not(feature = "std"), doc = "[`std::io::copy`]: <https://doc.rust-lang.org/nightly/std/io/fn.copy.html>")]
///
/// # Errors
///
/// This function will forward any non-interrupt
/// errors from both the reader and the writer.
pub fn copy<R: ?Sized + Read, W: ?Sized + Write>(r: &mut R, w: &mut W) -> Result<u64> {
	let mut tmp = [0; DEFAULT_BUF_SIZE];

	let mut total_count = 0;

	// Read from the reader into the temporary buffer.

	'main_loop: loop {
		match r.read(&mut tmp) {
			Ok(0) => {
				// End of file.

				break Ok(total_count);
			}

			Ok(count) => {
				let tmp = &tmp[..count];

				// Write from the temporary buffer into the writer.

				loop {
					match w.write(tmp) {
						Ok(0) => {
							// End of file.

							break 'main_loop Ok(total_count);
						}

						Ok(count) => {
							total_count += count as u64;
						}

						Err(ref e) if e.is_interrupted() => {}

						Err(e) => {
							break 'main_loop Err(e);
						}
					}
				}
			}

			Err(ref e) if e.is_interrupted() => {}

			Err(e) => {
				break Err(e);
			}
		}
	}
}