//
// jja: swiss army knife for chess file formats
// src/file.rs: Utilities for binary file I/O
//
// Copyright (c) 2023 Ali Polatel <alip@chesswob.org>
// SPDX-License-Identifier: GPL-3.0-or-later

use std::io::{self, Read, Write};

/// Writes an integer to a file using a specified number of bytes.
///
/// This function takes a mutable reference to a type implementing the `Write` trait, a length
/// (number of bytes), and an integer value. It writes the integer to the file using the specified
/// number of bytes in big-endian format.
///
/// # Arguments
///
/// * `f` - A mutable reference to a type implementing the `Write` trait.
/// * `l` - The length (number of bytes) to use when writing the integer.
/// * `r` - The integer value to write to the file.
///
/// # Returns
///
/// A `Result<(), io::Error>` indicating success or failure.
pub fn int_to_file<W: Write>(mut f: W, l: usize, r: u64) -> io::Result<()> {
    // Convert the integer to big endian bytes
    let bytes = r.to_be_bytes();

    // Write the relevant bytes to the file
    f.write_all(&bytes[8 - l..])?;

    Ok(())
}

/// Reads an integer from a file using a specified number of bytes.
///
/// This function takes a mutable reference to a type implementing the `Read` trait and a length
/// (number of bytes). It reads an integer from the file using the specified number of bytes in
/// big-endian format.
///
/// # Arguments
///
/// * `f` - A mutable reference to a type implementing the `Read` trait.
/// * `l` - The length (number of bytes) to use when reading the integer.
///
/// # Returns
///
/// A `Result<u64, io::Error>` containing the integer value read from the file or an error if
/// reading fails.
pub fn int_from_file<R: Read>(mut f: R, l: usize) -> io::Result<u64> {
    let mut bytes = [0u8; 8]; // Start with zero-filled bytes

    // Read exactly the number of bytes we need into the end of our buffer
    f.read_exact(&mut bytes[8 - l..])?;

    // Convert bytes to a u64 integer in big endian format
    Ok(u64::from_be_bytes(bytes))
}
