gcn_disk 0.5.0

Gamecube file header library and utilities.
Documentation
// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR MPL-2.0
// SPDX-FileCopyrightText: 2026 Gabriel Marcano <gabemarcano@yahoo.com>

use crate::error::Error;
use crate::metadata::Metadata;

use std::io;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;

/// Represents the metadata held by the GCN disk internal header.
pub struct Disc<T: Read + Seek> {
    /// Metadata from the disc, includes its header and FST filesystem
    pub metadata: Metadata,
    io: T,
}

impl<T: Read + Seek> Disc<T> {
    /// Creates a Disc by reading the metadata from the providing IO object.
    ///
    /// # Errors
    ///
    /// See [`Metadata::try_from`] for more details.
    pub fn try_from(io: T) -> Result<Self, Error> {
        let mut io = io;
        Ok(Self {
            metadata: Metadata::try_from(&mut io)?,
            io,
        })
    }

    /// Returns the data for the requested file if it exists.
    ///
    /// # Errors
    ///
    /// See [`Fst::get_file`](crate::Fst::get_file) for more details.
    pub fn get_file(&mut self, filepath: &str) -> Result<Vec<u8>, Error> {
        self.metadata.filesystem.get_file(&mut self.io, filepath)
    }

    // FIXME moving forward, does it make sense to copy the Fst fields here?
}

impl<T: Read + Seek> Read for Disc<T> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl<T: Read + Seek> Seek for Disc<T> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.io.seek(pos)
    }
}