1use std::{fmt, io};
2
3use nwnrs_localization::prelude::*;
4use serde::{Deserialize, Serialize};
5
6pub(crate) const HEADER_MAGIC: &str = "SSF ";
7pub(crate) const HEADER_VERSION: &str = "V1.0";
8pub(crate) const TABLE_OFFSET: u32 = 40;
9pub(crate) const ENTRY_DATA_SIZE: usize = 20;
10
11#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SsfError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
SsfError::Io(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Io",
&__self_0),
SsfError::Message(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Message", &__self_0),
}
}
}Debug)]
12pub enum SsfError {
14 Io(io::Error),
16 Message(String),
18}
19
20impl fmt::Display for SsfError {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Self::Io(error) => error.fmt(f),
24 Self::Message(message) => f.write_str(message),
25 }
26 }
27}
28
29impl std::error::Error for SsfError {}
30
31impl From<io::Error> for SsfError {
32 fn from(value: io::Error) -> Self {
33 Self::Io(value)
34 }
35}
36
37pub type SsfResult<T> = Result<T, SsfError>;
39
40#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SsfEntry {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "SsfEntry",
"raw_resref", &self.raw_resref, "resref", &self.resref, "strref",
&&self.strref)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SsfEntry {
#[inline]
fn clone(&self) -> SsfEntry {
SsfEntry {
raw_resref: ::core::clone::Clone::clone(&self.raw_resref),
resref: ::core::clone::Clone::clone(&self.resref),
strref: ::core::clone::Clone::clone(&self.strref),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SsfEntry {
#[inline]
fn eq(&self, other: &SsfEntry) -> bool {
self.raw_resref == other.raw_resref && self.resref == other.resref &&
self.strref == other.strref
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SsfEntry {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<[u8; 16]>;
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<StrRef>;
}
}Eq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SsfEntry {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SsfEntry", false as usize + 1 + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"raw_resref", &self.raw_resref)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"resref", &self.resref)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"strref", &self.strref)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SsfEntry {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __field2, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"raw_resref" => _serde::__private228::Ok(__Field::__field0),
"resref" => _serde::__private228::Ok(__Field::__field1),
"strref" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"raw_resref" =>
_serde::__private228::Ok(__Field::__field0),
b"resref" => _serde::__private228::Ok(__Field::__field1),
b"strref" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SsfEntry>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SsfEntry;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SsfEntry")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<[u8; 16]>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SsfEntry with 3 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SsfEntry with 3 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<StrRef>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct SsfEntry with 3 elements")),
};
_serde::__private228::Ok(SsfEntry {
raw_resref: __field0,
resref: __field1,
strref: __field2,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<[u8; 16]> =
_serde::__private228::None;
let mut __field1: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field2: _serde::__private228::Option<StrRef> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("raw_resref"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<[u8; 16]>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("resref"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("strref"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<StrRef>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("raw_resref")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("resref")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("strref")?,
};
_serde::__private228::Ok(SsfEntry {
raw_resref: __field0,
resref: __field1,
strref: __field2,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["raw_resref", "resref", "strref"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SsfEntry", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SsfEntry>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
42pub struct SsfEntry {
43 pub raw_resref: [u8; 16],
45 pub resref: String,
47 pub strref: StrRef,
49}
50
51impl SsfEntry {
52 pub fn new(resref: impl Into<String>, strref: StrRef) -> Self {
54 let resref = resref.into();
55 let mut raw_resref = [0_u8; 16];
56 let bytes = resref.as_bytes();
57 let count = bytes.len().min(raw_resref.len());
58 if let (Some(dst), Some(src)) = (raw_resref.get_mut(..count), bytes.get(..count)) {
59 dst.copy_from_slice(src);
60 }
61 Self {
62 raw_resref,
63 resref,
64 strref,
65 }
66 }
67
68 pub(crate) fn stored_resref_bytes(&self) -> io::Result<[u8; 16]> {
69 if decode_resref(&self.raw_resref) == self.resref {
70 return Ok(self.raw_resref);
71 }
72
73 if self.resref.len() > 16 {
74 return Err(io::Error::new(
75 io::ErrorKind::InvalidData,
76 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("resref {0:?} exceeds 16 bytes",
self.resref))
})format!("resref {:?} exceeds 16 bytes", self.resref),
77 ));
78 }
79
80 let mut padded = [0_u8; 16];
81 let bytes = self.resref.as_bytes();
82 if let Some(prefix) = padded.get_mut(..bytes.len()) {
83 prefix.copy_from_slice(bytes);
84 }
85 Ok(padded)
86 }
87}
88
89#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SsfRoot {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "SsfRoot",
"entries", &&self.entries)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SsfRoot {
#[inline]
fn clone(&self) -> SsfRoot {
SsfRoot { entries: ::core::clone::Clone::clone(&self.entries) }
}
}Clone, #[automatically_derived]
impl ::core::default::Default for SsfRoot {
#[inline]
fn default() -> SsfRoot {
SsfRoot { entries: ::core::default::Default::default() }
}
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for SsfRoot {
#[inline]
fn eq(&self, other: &SsfRoot) -> bool { self.entries == other.entries }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SsfRoot {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Vec<SsfEntry>>;
}
}Eq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SsfRoot {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SsfRoot", false as usize + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"entries", &self.entries)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SsfRoot {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"entries" => _serde::__private228::Ok(__Field::__field0),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"entries" => _serde::__private228::Ok(__Field::__field0),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SsfRoot>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SsfRoot;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SsfRoot")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<Vec<SsfEntry>>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SsfRoot with 1 element")),
};
_serde::__private228::Ok(SsfRoot { entries: __field0 })
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0:
_serde::__private228::Option<Vec<SsfEntry>> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("entries"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<SsfEntry>>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("entries")?,
};
_serde::__private228::Ok(SsfRoot { entries: __field0 })
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &["entries"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SsfRoot", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SsfRoot>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
91pub struct SsfRoot {
92 pub entries: Vec<SsfEntry>,
94}
95
96impl SsfRoot {
97 #[must_use]
99 pub fn new() -> Self {
100 Self::default()
101 }
102}
103
104pub(crate) fn decode_resref(raw: &[u8]) -> String {
105 let end = raw.iter().position(|byte| *byte == 0).unwrap_or(raw.len());
106 String::from_utf8_lossy(raw.get(..end).unwrap_or(&[])).to_string()
107}