nx_archive/
util.rs

1//! Utility helpers and traits for nx-archive.
2
3use std::io::{Read, Seek};
4
5/// A trait that combines Read and Seek, used to simplify type bounds.
6pub trait ReadSeek: Read + Seek {}
7impl<T: Read + Seek> ReadSeek for T {}
8
9use crate::{
10    formats::{Keyset, TitleKeys, cnmt::Cnmt},
11    io::SubFile,
12};
13
14pub trait TitleDataExt {
15    fn get_cnmts(
16        &mut self,
17        keyset: &Keyset,
18        title_keyset: Option<&TitleKeys>,
19    ) -> Result<Vec<Cnmt>, crate::error::Error>;
20    fn title_id(&self) -> Result<u64, crate::error::Error>;
21    fn title_id_serialized(&self) -> Result<String, crate::error::Error> {
22        Ok(format!("{:016X}", self.title_id()?))
23    }
24}
25
26pub trait FileEntryExt<R: Read + Seek> {
27    type FS: VirtualFSExt<R>;
28
29    /// Returns a virtual file reader that buffers and reads the file
30    ///
31    /// This is useful for reading files from archives, which may be compressed or encrypted.
32    /// And for reading large files, which may cause performance issues if the entire file is read into memory.
33    fn file_reader(&self, fs: &mut Self::FS) -> Result<SubFile<R>, crate::error::Error>;
34
35    /// Returns the size of the file in bytes.
36    fn file_size(&self) -> u64;
37
38    /// Read the whole file into memory, and returns a Vec<u8>.
39    ///
40    /// This is not recommended for large files, as it may cause performance issues.
41    fn read_bytes(&self, fs: &mut Self::FS, size: usize) -> Result<Vec<u8>, crate::error::Error>;
42
43    /// Get the file name of the entry.
44    fn file_name(&self) -> String;
45
46    /// Get the file extension, if any.
47    fn file_extension(&self) -> Option<String> {
48        self.file_name()
49            .split('.')
50            .last()
51            .map(|ext| ext.to_string())
52    }
53}
54
55pub trait VirtualFSExt<R: Read + Seek> {
56    type Entry: FileEntryExt<R, FS = Self>;
57
58    /// List files in the archive
59    fn list_files(&self) -> Result<Vec<Self::Entry>, crate::error::Error>;
60
61    /// Get a file by name
62    fn get_file(&self, name: &str) -> Result<Option<Self::Entry>, crate::error::Error>;
63
64    /// Create a SubFile reader for a given file entry
65    fn create_reader(&mut self, file: &Self::Entry) -> Result<SubFile<R>, crate::error::Error>;
66}