infinite_rs/common/
errors.rs

1//! Common errors used throughout `infinite-rs`.
2
3use num_enum::TryFromPrimitiveError;
4use std::io::Error as StdIoError;
5use std::num::TryFromIntError;
6use std::result::Result as StdResult;
7use std::string::FromUtf8Error;
8use thiserror::Error;
9
10use crate::{
11    module::header::ModuleVersion,
12    tag::{
13        datablock::TagSectionType,
14        structure::{TagStructLocation, TagStructType},
15    },
16};
17
18#[derive(Error, Debug)]
19/// Errors that can occur when reading a module file.
20pub enum ModuleError {
21    /// Incorrect magic number found in the module file header. Expected magic number is "ucsh" (0x64686F6D).
22    #[error("Incorrect module magic found! Expected '0x64686F6D', found {0:#X}!")]
23    IncorrectMagic(u32),
24    /// Incorrect version number found in the module file header. Expected version is 53.
25    /// While version 53 is the only fully supported version, other versions may also work.
26    #[error("Incorrect module version found!")]
27    IncorrectVersion(#[from] TryFromPrimitiveError<ModuleVersion>),
28    /// Invalid negative block index found in module file, indicating file corruption.
29    /// This error serves as a runtime assert.
30    #[error("Module file block index must be non-negative, found {0}")]
31    NegativeBlockIndex(i32),
32    /// Occurs when the [`is_compressed`](`crate::module::block::ModuleBlockEntry::is_compressed`) value is not 0 or 1
33    #[error("Value for is_compressed incorrect!")]
34    IncorrectCompressedValue,
35}
36
37#[derive(Error, Debug)]
38/// Errors that can occur when reading a tag file.
39pub enum TagError {
40    /// Incorrect magic number found in the tag file header. Expected magic number is "mohd" (0x68736375).
41    #[error("Incorrect magic found! Expected '0x68736375', found {0:#X}!")]
42    IncorrectMagic(u32),
43    /// Incorrect version number found in the tag file header. Expected version is 27.
44    /// Version 27 is used across all Infinite versions and matches Halo 5, though with different structures.
45    #[error("Incorrect version found! Expected '27', found {0}!")]
46    IncorrectVersion(i32),
47    /// File data has not been loaded. Operations require [`data_stream`](`crate::module::file::ModuleFileEntry::data_stream`) to be initialized.
48    #[error("Not been loaded yet!")]
49    NotLoaded,
50    /// Main struct designated by [`MainStruct`](`crate::tag::structure::TagStructType`) was not found in tag file.
51    #[error("Main struct not found!")]
52    MainStructNotFound,
53    /// Tag metadata headers [`tag_info`](`crate::module::file::ModuleFileEntry::tag_info`) are missing.
54    /// This occurs when attempting to read metadata from a [`RawFile`](`crate::module::file::FileEntryFlags::RAW_FILE`).
55    #[error("Does not contain tag info!")]
56    NoTagInfo,
57    /// Failed to convert integer to [`TagSectionType`].
58    /// This error should not occur as [`TagSectionType`] enum is exhaustive.
59    #[error("Invalid TagStruct type encountered!")]
60    InvalidTagSection(#[from] TryFromPrimitiveError<TagSectionType>),
61    /// Failed to convert integer to [`TagStructType`].
62    /// This error should not occur as [`TagStructType`] enum is exhaustive.
63    #[error("Invalid TagStruct type encountered!")]
64    InvalidTagStruct(#[from] TryFromPrimitiveError<TagStructType>),
65    /// Failed to convert primitive to enum in [`common_types`](`crate::tag::types::common_types`).
66    #[error("Failed to convert primitive to enum")]
67    NumEnumError,
68    /// Recursion depth reached 3 when trying to get tag path.
69    /// This should never ever happen, if it has, something has gone very wrong.
70    #[error("Recursion depth reached 3!")]
71    RecursionDepth,
72    /// Failed to convert integer to [`TagStructLocation`].
73    /// This error should not occur as [`TagStructLocation`] enum is exhaustive.
74    #[error("Invalid TagStruct location encountered!")]
75    InvalidTagStructLocation(#[from] TryFromPrimitiveError<TagStructLocation>),
76}
77
78#[derive(Error, Debug)]
79/// Errors that can occur when decompressing data.
80pub enum DecompressionError {
81    /// Buffer size is insufficient for decompressed data.
82    /// This should not occur in Infinite module decompression.
83    #[error("Buffer size overflow")]
84    BufferSizeOverflow,
85    /// Decompression failed with Kraken decompressor error code.
86    /// Negative error codes indicate decompression failure.
87    #[error("Decompression failed with error code {0}")]
88    DecompressionFailed(i32),
89}
90
91#[derive(Error, Debug)]
92/// Standard error type used throughout `infinite-rs`.
93pub enum Error {
94    /// IO error from [`std::io`] operations.
95    #[error("Failed to read from buffer!")]
96    ReadError(#[from] StdIoError),
97    /// UTF-8 decoding error in [`read_fixed_string`](`crate::common::extensions::BufReaderExt::read_fixed_string`).
98    #[error("Incorrect UTF-8 encoding found when reading string!")]
99    Utf8ReadingError(#[from] FromUtf8Error),
100    /// Kraken decompression error.
101    #[error("Error occurred while decompressing!")]
102    DecompressionError(#[from] DecompressionError),
103    /// Module file loading error.
104    #[error("Error occurred while loading a module!")]
105    ModuleError(#[from] ModuleError),
106    /// Integer type conversion error.
107    #[error("Integer conversion failed!")]
108    TryFromIntError(#[from] TryFromIntError),
109    /// Tag file loading error.
110    #[error("Error occurred while loading a tag!")]
111    TagError(#[from] TagError),
112}
113
114/// Standard result type used throughout `infinite-rs`.
115pub type Result<T> = StdResult<T, Error>;