1use std::{fmt, io};
2
3use nwnrs_io::prelude::*;
4use nwnrs_localization::prelude::*;
5
6type GffByte = u8;
7type GffChar = i8;
8type GffWord = u16;
9type GffShort = i16;
10type GffDword = u32;
11type GffInt = i32;
12type GffFloat = f32;
13type GffDword64 = u64;
14type GffInt64 = i64;
15type GffDouble = f64;
16type GffCExoString = String;
17type GffResRef = String;
18type GffVoid = Vec<u8>;
19type GffList = Vec<GffStruct>;
20
21pub(crate) const HEADER_SIZE: usize = 56;
22
23#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffCExoLocString {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"GffCExoLocString", "str_ref", &self.str_ref, "entries",
&&self.entries)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffCExoLocString {
#[inline]
fn clone(&self) -> GffCExoLocString {
GffCExoLocString {
str_ref: ::core::clone::Clone::clone(&self.str_ref),
entries: ::core::clone::Clone::clone(&self.entries),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffCExoLocString {
#[inline]
fn eq(&self, other: &GffCExoLocString) -> bool {
self.str_ref == other.str_ref && self.entries == other.entries
}
}PartialEq)]
25pub struct GffCExoLocString {
29 pub str_ref: StrRef,
31 pub entries: Vec<(i32, String)>,
33}
34
35impl Default for GffCExoLocString {
36 fn default() -> Self {
37 Self {
38 str_ref: BAD_STRREF,
39 entries: Vec::new(),
40 }
41 }
42}
43
44#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffFieldKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
GffFieldKind::Byte => "Byte",
GffFieldKind::Char => "Char",
GffFieldKind::Word => "Word",
GffFieldKind::Short => "Short",
GffFieldKind::Dword => "Dword",
GffFieldKind::Int => "Int",
GffFieldKind::Dword64 => "Dword64",
GffFieldKind::Int64 => "Int64",
GffFieldKind::Float => "Float",
GffFieldKind::Double => "Double",
GffFieldKind::CExoString => "CExoString",
GffFieldKind::ResRef => "ResRef",
GffFieldKind::CExoLocString => "CExoLocString",
GffFieldKind::Void => "Void",
GffFieldKind::Struct => "Struct",
GffFieldKind::List => "List",
})
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffFieldKind {
#[inline]
fn clone(&self) -> GffFieldKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for GffFieldKind { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for GffFieldKind {
#[inline]
fn eq(&self, other: &GffFieldKind) -> 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 GffFieldKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for GffFieldKind {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash)]
46#[repr(u32)]
47pub enum GffFieldKind {
50 Byte = 0,
52 Char = 1,
54 Word = 2,
56 Short = 3,
58 Dword = 4,
60 Int = 5,
62 Dword64 = 6,
64 Int64 = 7,
66 Float = 8,
68 Double = 9,
70 CExoString = 10,
72 ResRef = 11,
74 CExoLocString = 12,
76 Void = 13,
78 Struct = 14,
80 List = 15,
82}
83
84impl GffFieldKind {
85 #[must_use]
87 pub fn is_complex(self) -> bool {
88 #[allow(non_exhaustive_omitted_patterns)] match self {
Self::Dword64 | Self::Int64 | Self::Double | Self::CExoString |
Self::ResRef | Self::CExoLocString | Self::Void | Self::Struct |
Self::List => true,
_ => false,
}matches!(
89 self,
90 Self::Dword64
91 | Self::Int64
92 | Self::Double
93 | Self::CExoString
94 | Self::ResRef
95 | Self::CExoLocString
96 | Self::Void
97 | Self::Struct
98 | Self::List
99 )
100 }
101
102 pub(crate) fn from_u32(value: u32) -> Option<Self> {
103 Some(match value {
104 0 => Self::Byte,
105 1 => Self::Char,
106 2 => Self::Word,
107 3 => Self::Short,
108 4 => Self::Dword,
109 5 => Self::Int,
110 6 => Self::Dword64,
111 7 => Self::Int64,
112 8 => Self::Float,
113 9 => Self::Double,
114 10 => Self::CExoString,
115 11 => Self::ResRef,
116 12 => Self::CExoLocString,
117 13 => Self::Void,
118 14 => Self::Struct,
119 15 => Self::List,
120 _ => return None,
121 })
122 }
123}
124
125#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffValue {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
GffValue::Byte(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Byte",
&__self_0),
GffValue::Char(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Char",
&__self_0),
GffValue::Word(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Word",
&__self_0),
GffValue::Short(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Short",
&__self_0),
GffValue::Dword(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Dword",
&__self_0),
GffValue::Int(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Int",
&__self_0),
GffValue::Float(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Float",
&__self_0),
GffValue::Dword64(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Dword64", &__self_0),
GffValue::Int64(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Int64",
&__self_0),
GffValue::Double(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Double",
&__self_0),
GffValue::CExoString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"CExoString", &__self_0),
GffValue::ResRef(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "ResRef",
&__self_0),
GffValue::CExoLocString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"CExoLocString", &__self_0),
GffValue::Void(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Void",
&__self_0),
GffValue::Struct(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Struct",
&__self_0),
GffValue::List(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "List",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffValue {
#[inline]
fn clone(&self) -> GffValue {
match self {
GffValue::Byte(__self_0) =>
GffValue::Byte(::core::clone::Clone::clone(__self_0)),
GffValue::Char(__self_0) =>
GffValue::Char(::core::clone::Clone::clone(__self_0)),
GffValue::Word(__self_0) =>
GffValue::Word(::core::clone::Clone::clone(__self_0)),
GffValue::Short(__self_0) =>
GffValue::Short(::core::clone::Clone::clone(__self_0)),
GffValue::Dword(__self_0) =>
GffValue::Dword(::core::clone::Clone::clone(__self_0)),
GffValue::Int(__self_0) =>
GffValue::Int(::core::clone::Clone::clone(__self_0)),
GffValue::Float(__self_0) =>
GffValue::Float(::core::clone::Clone::clone(__self_0)),
GffValue::Dword64(__self_0) =>
GffValue::Dword64(::core::clone::Clone::clone(__self_0)),
GffValue::Int64(__self_0) =>
GffValue::Int64(::core::clone::Clone::clone(__self_0)),
GffValue::Double(__self_0) =>
GffValue::Double(::core::clone::Clone::clone(__self_0)),
GffValue::CExoString(__self_0) =>
GffValue::CExoString(::core::clone::Clone::clone(__self_0)),
GffValue::ResRef(__self_0) =>
GffValue::ResRef(::core::clone::Clone::clone(__self_0)),
GffValue::CExoLocString(__self_0) =>
GffValue::CExoLocString(::core::clone::Clone::clone(__self_0)),
GffValue::Void(__self_0) =>
GffValue::Void(::core::clone::Clone::clone(__self_0)),
GffValue::Struct(__self_0) =>
GffValue::Struct(::core::clone::Clone::clone(__self_0)),
GffValue::List(__self_0) =>
GffValue::List(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffValue {
#[inline]
fn eq(&self, other: &GffValue) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(GffValue::Byte(__self_0), GffValue::Byte(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Char(__self_0), GffValue::Char(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Word(__self_0), GffValue::Word(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Short(__self_0), GffValue::Short(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Dword(__self_0), GffValue::Dword(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Int(__self_0), GffValue::Int(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Float(__self_0), GffValue::Float(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Dword64(__self_0), GffValue::Dword64(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Int64(__self_0), GffValue::Int64(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Double(__self_0), GffValue::Double(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::CExoString(__self_0),
GffValue::CExoString(__arg1_0)) => __self_0 == __arg1_0,
(GffValue::ResRef(__self_0), GffValue::ResRef(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::CExoLocString(__self_0),
GffValue::CExoLocString(__arg1_0)) => __self_0 == __arg1_0,
(GffValue::Void(__self_0), GffValue::Void(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::Struct(__self_0), GffValue::Struct(__arg1_0)) =>
__self_0 == __arg1_0,
(GffValue::List(__self_0), GffValue::List(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq)]
127pub enum GffValue {
129 Byte(GffByte),
131 Char(GffChar),
133 Word(GffWord),
135 Short(GffShort),
137 Dword(GffDword),
139 Int(GffInt),
141 Float(GffFloat),
143 Dword64(GffDword64),
145 Int64(GffInt64),
147 Double(GffDouble),
149 CExoString(GffCExoString),
151 ResRef(GffResRef),
153 CExoLocString(GffCExoLocString),
155 Void(GffVoid),
157 Struct(GffStruct),
159 List(GffList),
161}
162
163impl GffValue {
164 #[must_use]
166 pub fn kind(&self) -> GffFieldKind {
167 match self {
168 Self::Byte(_) => GffFieldKind::Byte,
169 Self::Char(_) => GffFieldKind::Char,
170 Self::Word(_) => GffFieldKind::Word,
171 Self::Short(_) => GffFieldKind::Short,
172 Self::Dword(_) => GffFieldKind::Dword,
173 Self::Int(_) => GffFieldKind::Int,
174 Self::Float(_) => GffFieldKind::Float,
175 Self::Dword64(_) => GffFieldKind::Dword64,
176 Self::Int64(_) => GffFieldKind::Int64,
177 Self::Double(_) => GffFieldKind::Double,
178 Self::CExoString(_) => GffFieldKind::CExoString,
179 Self::ResRef(_) => GffFieldKind::ResRef,
180 Self::CExoLocString(_) => GffFieldKind::CExoLocString,
181 Self::Void(_) => GffFieldKind::Void,
182 Self::Struct(_) => GffFieldKind::Struct,
183 Self::List(_) => GffFieldKind::List,
184 }
185 }
186}
187
188#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffField {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "GffField",
"value", &self.value, "provenance", &&self.provenance)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffField {
#[inline]
fn clone(&self) -> GffField {
GffField {
value: ::core::clone::Clone::clone(&self.value),
provenance: ::core::clone::Clone::clone(&self.provenance),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffField {
#[inline]
fn eq(&self, other: &GffField) -> bool {
self.value == other.value && self.provenance == other.provenance
}
}PartialEq)]
190pub struct GffField {
193 pub(crate) value: GffValue,
194 pub(crate) provenance: Option<GffFieldProvenance>,
195}
196
197impl GffField {
198 #[must_use]
200 pub fn new(value: GffValue) -> Self {
201 Self {
202 value,
203 provenance: None,
204 }
205 }
206
207 pub(crate) fn with_provenance(value: GffValue, provenance: GffFieldProvenance) -> Self {
208 Self {
209 value,
210 provenance: Some(provenance),
211 }
212 }
213
214 #[must_use]
216 pub fn kind(&self) -> GffFieldKind {
217 self.value.kind()
218 }
219
220 #[must_use]
222 pub fn value(&self) -> &GffValue {
223 &self.value
224 }
225}
226
227#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffFieldProvenance {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"GffFieldProvenance", "label_bytes", &self.label_bytes,
"original_value", &self.original_value, "raw_data_or_offset",
&self.raw_data_or_offset, "raw_field_data", &&self.raw_field_data)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffFieldProvenance {
#[inline]
fn clone(&self) -> GffFieldProvenance {
GffFieldProvenance {
label_bytes: ::core::clone::Clone::clone(&self.label_bytes),
original_value: ::core::clone::Clone::clone(&self.original_value),
raw_data_or_offset: ::core::clone::Clone::clone(&self.raw_data_or_offset),
raw_field_data: ::core::clone::Clone::clone(&self.raw_field_data),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffFieldProvenance {
#[inline]
fn eq(&self, other: &GffFieldProvenance) -> bool {
self.raw_data_or_offset == other.raw_data_or_offset &&
self.label_bytes == other.label_bytes &&
self.original_value == other.original_value &&
self.raw_field_data == other.raw_field_data
}
}PartialEq)]
228pub(crate) struct GffFieldProvenance {
229 pub(crate) label_bytes: [u8; 16],
230 pub(crate) original_value: GffValue,
231 pub(crate) raw_data_or_offset: i32,
232 pub(crate) raw_field_data: Option<Vec<u8>>,
233}
234
235#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffStruct {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "GffStruct",
"id", &self.id, "fields", &self.fields, "provenance",
&&self.provenance)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffStruct {
#[inline]
fn clone(&self) -> GffStruct {
GffStruct {
id: ::core::clone::Clone::clone(&self.id),
fields: ::core::clone::Clone::clone(&self.fields),
provenance: ::core::clone::Clone::clone(&self.provenance),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffStruct {
#[inline]
fn eq(&self, other: &GffStruct) -> bool {
self.id == other.id && self.fields == other.fields &&
self.provenance == other.provenance
}
}PartialEq)]
241pub struct GffStruct {
243 pub id: i32,
245 pub(crate) fields: Vec<(String, GffField)>,
246 pub(crate) provenance: Option<GffStructProvenance>,
247}
248
249#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffStructProvenance {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"GffStructProvenance", "field_labels", &&self.field_labels)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffStructProvenance {
#[inline]
fn clone(&self) -> GffStructProvenance {
GffStructProvenance {
field_labels: ::core::clone::Clone::clone(&self.field_labels),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffStructProvenance {
#[inline]
fn eq(&self, other: &GffStructProvenance) -> bool {
self.field_labels == other.field_labels
}
}PartialEq)]
250pub(crate) struct GffStructProvenance {
251 pub(crate) field_labels: Vec<String>,
252}
253
254impl GffStruct {
255 #[must_use]
257 pub fn new(id: i32) -> Self {
258 Self {
259 id,
260 fields: Vec::new(),
261 provenance: None,
262 }
263 }
264
265 #[must_use]
267 pub fn fields(&self) -> &[(String, GffField)] {
268 self.fields.as_slice()
269 }
270
271 pub fn put_field(&mut self, label: impl Into<String>, field: GffField) -> GffResult<()> {
277 let label = label.into();
278 ensure_label(&label)?;
279
280 if let Some((_, existing)) = self.fields.iter_mut().find(|(name, _)| *name == label) {
281 *existing = field;
282 } else {
283 self.fields.push((label, field));
284 }
285
286 Ok(())
287 }
288
289 pub fn put_value(&mut self, label: impl Into<String>, value: GffValue) -> GffResult<()> {
295 self.put_field(label, GffField::new(value))
296 }
297
298 #[must_use]
300 pub fn get_field(&self, label: &str) -> Option<&GffField> {
301 self.fields
302 .iter()
303 .find_map(|(name, field)| (name == label).then_some(field))
304 }
305
306 pub fn remove(&mut self, label: &str) -> Option<GffField> {
308 let idx = self.fields.iter().position(|(name, _)| name == label)?;
309 Some(self.fields.remove(idx).1)
310 }
311}
312
313#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffRoot {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f, "GffRoot",
"file_type", &self.file_type, "file_version", &self.file_version,
"root", &self.root, "source_bytes", &self.source_bytes,
"source_snapshot", &&self.source_snapshot)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffRoot {
#[inline]
fn clone(&self) -> GffRoot {
GffRoot {
file_type: ::core::clone::Clone::clone(&self.file_type),
file_version: ::core::clone::Clone::clone(&self.file_version),
root: ::core::clone::Clone::clone(&self.root),
source_bytes: ::core::clone::Clone::clone(&self.source_bytes),
source_snapshot: ::core::clone::Clone::clone(&self.source_snapshot),
}
}
}Clone)]
319pub struct GffRoot {
321 pub file_type: String,
323 pub file_version: String,
325 pub root: GffStruct,
327 pub(crate) source_bytes: Option<Vec<u8>>,
328 pub(crate) source_snapshot: Option<GffRootSnapshot>,
329}
330
331#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffRootSnapshot {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"GffRootSnapshot", "file_type", &self.file_type, "file_version",
&self.file_version, "root", &&self.root)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GffRootSnapshot {
#[inline]
fn clone(&self) -> GffRootSnapshot {
GffRootSnapshot {
file_type: ::core::clone::Clone::clone(&self.file_type),
file_version: ::core::clone::Clone::clone(&self.file_version),
root: ::core::clone::Clone::clone(&self.root),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for GffRootSnapshot {
#[inline]
fn eq(&self, other: &GffRootSnapshot) -> bool {
self.file_type == other.file_type &&
self.file_version == other.file_version &&
self.root == other.root
}
}PartialEq)]
332pub(crate) struct GffRootSnapshot {
333 pub(crate) file_type: String,
334 pub(crate) file_version: String,
335 pub(crate) root: GffStruct,
336}
337
338impl GffRoot {
339 pub fn new(file_type: impl Into<String>) -> Self {
344 Self {
345 file_type: file_type.into(),
346 file_version: "V3.2".to_string(),
347 root: GffStruct::new(-1),
348 source_bytes: None,
349 source_snapshot: None,
350 }
351 }
352
353 #[must_use]
355 pub fn fields(&self) -> &[(String, GffField)] {
356 self.root.fields()
357 }
358
359 pub fn put_value(&mut self, label: impl Into<String>, value: GffValue) -> GffResult<()> {
365 self.root.put_value(label, value)
366 }
367
368 pub(crate) fn snapshot(&self) -> GffRootSnapshot {
369 GffRootSnapshot {
370 file_type: self.file_type.clone(),
371 file_version: self.file_version.clone(),
372 root: self.root.clone(),
373 }
374 }
375}
376
377#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GffError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
GffError::Io(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Io",
&__self_0),
GffError::Expectation(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Expectation", &__self_0),
GffError::Message(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Message", &__self_0),
}
}
}Debug)]
379pub enum GffError {
380 Io(io::Error),
382 Expectation(ExpectationError),
384 Message(String),
386}
387
388impl GffError {
389 pub(crate) fn msg(message: impl Into<String>) -> Self {
390 Self::Message(message.into())
391 }
392}
393
394impl fmt::Display for GffError {
395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396 match self {
397 Self::Io(error) => error.fmt(f),
398 Self::Expectation(error) => error.fmt(f),
399 Self::Message(message) => f.write_str(message),
400 }
401 }
402}
403
404impl std::error::Error for GffError {}
405
406impl From<io::Error> for GffError {
407 fn from(value: io::Error) -> Self {
408 Self::Io(value)
409 }
410}
411
412impl From<ExpectationError> for GffError {
413 fn from(value: ExpectationError) -> Self {
414 Self::Expectation(value)
415 }
416}
417
418pub type GffResult<T> = Result<T, GffError>;
420
421pub(crate) fn ensure_label(label: &str) -> GffResult<()> {
422 nwnrs_io::expect(
423 label.len() <= 16,
424 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid GFF label length for {0:?}",
label))
})format!("invalid GFF label length for {label:?}"),
425 )?;
426 Ok(())
427}
428
429impl PartialEq for GffRoot {
430 fn eq(&self, other: &Self) -> bool {
431 self.file_type == other.file_type
432 && self.file_version == other.file_version
433 && self.root == other.root
434 }
435}