Skip to main content

terra_wld/
error.rs

1use std::io;
2
3use cs_datetime_parse::{OutOfRangeError, ParseError};
4use terra_types::TerrariaFileType;
5use thiserror::Error;
6
7use crate::{MAGIC_NUMBER, SUPPORTED_VERSIONS};
8
9pub type Result<T> = core::result::Result<T, Error>;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[non_exhaustive]
13pub enum OffsetType {
14	Header,
15	Tiles,
16	Chests,
17	Signs,
18	Entities,
19	TileEntites,
20	WeightedPressurePlates,
21	Homes,
22	Bestiary,
23	JourneyPowers,
24	Footer,
25}
26
27impl OffsetType {
28	pub const ALL: [OffsetType; 11] = [
29		OffsetType::Header,
30		OffsetType::Tiles,
31		OffsetType::Chests,
32		OffsetType::Signs,
33		OffsetType::Entities,
34		OffsetType::TileEntites,
35		OffsetType::WeightedPressurePlates,
36		OffsetType::Homes,
37		OffsetType::Bestiary,
38		OffsetType::JourneyPowers,
39		OffsetType::Footer,
40	];
41
42	pub const fn name(self) -> &'static str {
43		match self {
44			Self::Header => "header",
45			Self::Tiles => "tiles",
46			Self::Chests => "chests",
47			Self::Signs => "signs",
48			Self::Entities => "entities",
49			Self::TileEntites => "tile entities",
50			Self::WeightedPressurePlates => "weighted pressure plates",
51			Self::Homes => "homes",
52			Self::Bestiary => "bestiary",
53			Self::JourneyPowers => "journey powers",
54			Self::Footer => "footer",
55		}
56	}
57}
58
59#[derive(Error, Debug)]
60pub enum Error {
61	#[error("io error")]
62	Io(#[from] io::Error),
63
64	#[error("invalid magic number expected b\"{}\", found b\"{}\"", format_u8_array(MAGIC_NUMBER), format_u8_array(.found))]
65	InvalidMagicNumber { found: Vec<u8> },
66
67	#[error("Creation time {0}")]
68	CreationTimeWrite(OutOfRangeError),
69
70	#[error("Last played {0}")]
71	LastPlayedWrite(OutOfRangeError),
72
73	#[error("Creation time {0}")]
74	CreationTimeRead(ParseError),
75
76	#[error("Last played{0}")]
77	LastPlayedRead(ParseError),
78
79	#[error("the version {0} is not supported, supported versions: {SUPPORTED_VERSIONS:?}")]
80	UnsupportedVersion(i32),
81
82	#[error("invalid file type expected {}, found {}", TerrariaFileType::World.name(), .0.name())]
83	InvalidFileType(TerrariaFileType),
84
85	#[error("invalid footer")]
86	InvalidFooter,
87
88	#[error("invalid {} offset expected 0x{expected:X} found 0x{found:X}", .offset_type.name())]
89	InvalidOffset {
90		offset_type: OffsetType,
91		expected: u64,
92		found: u64,
93	},
94
95	#[error("unknown tile entity({})", .id)]
96	UnknownTileEntity { id: u8 },
97
98	#[error("{0}")]
99	SerdeError(serde_json::Error),
100}
101
102fn format_u8_array(array: &[u8]) -> String {
103	let mut text = String::with_capacity(array.len());
104	for byte in array {
105		if !byte.is_ascii_graphic() {
106			text.push_str("\\x");
107			text.push_str(&byte.to_string());
108			continue;
109		}
110
111		let char = *byte as char;
112		if char == '\\' {
113			text.push_str("\\\\");
114			continue;
115		}
116
117		text.push(char);
118	}
119
120	text
121}