1use std::{
2 collections::{BTreeMap, hash_map::RandomState},
3 fmt, io,
4 time::SystemTime,
5};
6
7use indexmap::IndexMap;
8use nwnrs_compressedbuf::prelude::*;
9use nwnrs_encoding::prelude::*;
10use nwnrs_io::prelude::*;
11use nwnrs_resman::prelude::*;
12use nwnrs_resref::prelude::*;
13
14pub(crate) const HEADER_SIZE: u64 = 160;
15pub(crate) const VALID_ERF_TYPES: [&str; 4] = ["NWM ", "MOD ", "ERF ", "HAK "];
16
17#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErfError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ErfError::Io(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Io",
&__self_0),
ErfError::ResMan(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "ResMan",
&__self_0),
ErfError::ResRef(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "ResRef",
&__self_0),
ErfError::Compression(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Compression", &__self_0),
ErfError::Expectation(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Expectation", &__self_0),
ErfError::Encoding(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Encoding", &__self_0),
ErfError::Message(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Message", &__self_0),
}
}
}Debug)]
18pub enum ErfError {
20 Io(io::Error),
22 ResMan(ResManError),
25 ResRef(ResRefError),
27 Compression(CompressedBufError),
29 Expectation(ExpectationError),
31 Encoding(EncodingConversionError),
33 Message(String),
35}
36
37impl ErfError {
38 pub(crate) fn msg(message: impl Into<String>) -> Self {
39 Self::Message(message.into())
40 }
41}
42
43impl fmt::Display for ErfError {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 Self::Io(error) => error.fmt(f),
47 Self::ResMan(error) => error.fmt(f),
48 Self::ResRef(error) => error.fmt(f),
49 Self::Compression(error) => error.fmt(f),
50 Self::Expectation(error) => error.fmt(f),
51 Self::Encoding(error) => error.fmt(f),
52 Self::Message(message) => f.write_str(message),
53 }
54 }
55}
56
57impl std::error::Error for ErfError {}
58
59impl From<io::Error> for ErfError {
60 fn from(value: io::Error) -> Self {
61 Self::Io(value)
62 }
63}
64
65impl From<ResManError> for ErfError {
66 fn from(value: ResManError) -> Self {
67 Self::ResMan(value)
68 }
69}
70
71impl From<ResRefError> for ErfError {
72 fn from(value: ResRefError) -> Self {
73 Self::ResRef(value)
74 }
75}
76
77impl From<CompressedBufError> for ErfError {
78 fn from(value: CompressedBufError) -> Self {
79 Self::Compression(value)
80 }
81}
82
83impl From<ExpectationError> for ErfError {
84 fn from(value: ExpectationError) -> Self {
85 Self::Expectation(value)
86 }
87}
88
89impl From<EncodingConversionError> for ErfError {
90 fn from(value: EncodingConversionError) -> Self {
91 Self::Encoding(value)
92 }
93}
94
95pub type ErfResult<T> = Result<T, ErfError>;
97
98#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErfVersion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self { ErfVersion::V1 => "V1", ErfVersion::E1 => "E1", })
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ErfVersion {
#[inline]
fn clone(&self) -> ErfVersion { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ErfVersion { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for ErfVersion {
#[inline]
fn eq(&self, other: &ErfVersion) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ErfVersion {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
99pub enum ErfVersion {
101 V1,
103 E1,
106}
107
108#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErfWriteOptions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ErfWriteOptions", "resource_list_padding",
&&self.resource_list_padding)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ErfWriteOptions {
#[inline]
fn clone(&self) -> ErfWriteOptions {
let _: ::core::clone::AssertParamIsClone<u64>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ErfWriteOptions { }Copy, #[automatically_derived]
impl ::core::default::Default for ErfWriteOptions {
#[inline]
fn default() -> ErfWriteOptions {
ErfWriteOptions {
resource_list_padding: ::core::default::Default::default(),
}
}
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for ErfWriteOptions {
#[inline]
fn eq(&self, other: &ErfWriteOptions) -> bool {
self.resource_list_padding == other.resource_list_padding
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ErfWriteOptions {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u64>;
}
}Eq)]
109pub struct ErfWriteOptions {
111 pub resource_list_padding: u64,
113}
114
115#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Erf {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["mtime", "file_type", "file_version", "filename", "build_year",
"build_day", "str_ref", "loc_strings", "entries", "oid",
"resource_list_padding"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.mtime, &self.file_type, &self.file_version,
&self.filename, &self.build_year, &self.build_day,
&self.str_ref, &self.loc_strings, &self.entries, &self.oid,
&&self.resource_list_padding];
::core::fmt::Formatter::debug_struct_fields_finish(f, "Erf", names,
values)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Erf {
#[inline]
fn clone(&self) -> Erf {
Erf {
mtime: ::core::clone::Clone::clone(&self.mtime),
file_type: ::core::clone::Clone::clone(&self.file_type),
file_version: ::core::clone::Clone::clone(&self.file_version),
filename: ::core::clone::Clone::clone(&self.filename),
build_year: ::core::clone::Clone::clone(&self.build_year),
build_day: ::core::clone::Clone::clone(&self.build_day),
str_ref: ::core::clone::Clone::clone(&self.str_ref),
loc_strings: ::core::clone::Clone::clone(&self.loc_strings),
entries: ::core::clone::Clone::clone(&self.entries),
oid: ::core::clone::Clone::clone(&self.oid),
resource_list_padding: ::core::clone::Clone::clone(&self.resource_list_padding),
}
}
}Clone)]
116pub struct Erf {
125 pub mtime: SystemTime,
127 pub file_type: String,
130 pub file_version: ErfVersion,
132 pub(crate) filename: String,
133 pub build_year: i32,
135 pub build_day: i32,
137 pub str_ref: i32,
139 pub(crate) loc_strings: BTreeMap<i32, String>,
140 pub(crate) entries: IndexMap<ResRef, Res, RandomState>,
141 pub(crate) oid: Option<String>,
142 pub(crate) resource_list_padding: u64,
143}
144
145impl Erf {
146 #[must_use]
148 pub fn filename(&self) -> &str {
149 &self.filename
150 }
151
152 #[must_use]
154 pub fn loc_strings(&self) -> &BTreeMap<i32, String> {
155 &self.loc_strings
156 }
157
158 #[must_use]
160 pub fn entries(&self) -> &IndexMap<ResRef, Res, RandomState> {
161 &self.entries
162 }
163
164 #[must_use]
166 pub fn oid(&self) -> Option<&str> {
167 self.oid.as_deref()
168 }
169
170 #[must_use]
172 pub fn resource_list_padding(&self) -> u64 {
173 self.resource_list_padding
174 }
175}
176
177impl fmt::Display for Erf {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.write_fmt(format_args!("Erf:{0}", self.filename))write!(f, "Erf:{}", self.filename)
180 }
181}
182
183impl ResContainer for Erf {
184 fn contains(&self, rr: &ResRef) -> bool {
185 self.entries.contains_key(rr)
186 }
187
188 fn demand(&self, rr: &ResRef) -> ResManResult<Res> {
189 self.entries
190 .get(rr)
191 .cloned()
192 .ok_or_else(|| ResManError::Message(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("not found: {0}", rr))
})format!("not found: {rr}")))
193 }
194
195 fn count(&self) -> usize {
196 self.entries.len()
197 }
198
199 fn contents(&self) -> Vec<ResRef> {
200 self.entries.keys().cloned().collect()
201 }
202}
203
204#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErfResMeta {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f, "ErfResMeta",
"offset", &self.offset, "disk_size", &self.disk_size,
"uncompressed_size", &self.uncompressed_size, "compression",
&&self.compression)
}
}Debug)]
205pub(crate) struct ErfResMeta {
206 pub offset: u64,
207 pub disk_size: usize,
208 pub uncompressed_size: usize,
209 pub compression: nwnrs_exo::ExoResFileCompressionType,
210}