use std::fmt;
use std::mem::transmute;
use std::collections::HashMap;
const USER_TLK_MASK: u32 = 0x8000_0000;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct StrRef(pub(crate) u32);
impl StrRef {
#[inline]
pub fn is_user(&self) -> bool { self.0 & USER_TLK_MASK != 0 }
#[inline]
pub fn code(&self) -> u32 { self.0 & !USER_TLK_MASK }
}
impl fmt::Debug for StrRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "code: {}, user: {}", self.code(), self.is_user())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum Language {
English = 0,
French = 1,
German = 2,
Italian = 3,
Spanish = 4,
Polish = 5,
Korean = 128,
ChineseTraditional = 129,
ChineseSimplified = 130,
Japanese= 131,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum Gender {
Male = 0,
Female = 1,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct StringKey(pub(crate) u32);
impl StringKey {
pub fn language(&self) -> Language { unsafe { transmute(self.0 >> 1) } }
pub fn gender(&self) -> Gender { unsafe { transmute(self.0 % 2) } }
}
impl From<(Language, Gender)> for StringKey {
#[inline]
fn from(value: (Language, Gender)) -> Self {
StringKey(((value.0 as u32) << 1) | value.1 as u32)
}
}
impl Into<u32> for StringKey {
#[inline]
fn into(self) -> u32 { self.0 }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SubString {
pub key: StringKey,
pub string: String,
}
impl From<(StringKey, String)> for SubString {
#[inline]
fn from(value: (StringKey, String)) -> Self {
SubString { key: value.0, string: value.1 }
}
}
impl Into<(StringKey, String)> for SubString {
#[inline]
fn into(self) -> (StringKey, String) {
(self.key, self.string)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LocString {
pub str_ref: StrRef,
pub strings: Vec<SubString>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GffString {
External(StrRef),
Internal(HashMap<StringKey, String>),
}
impl From<LocString> for GffString {
fn from(value: LocString) -> Self {
use self::GffString::*;
match value.str_ref {
StrRef(0xFFFFFFFF) => Internal(value.strings.into_iter().map(Into::into).collect()),
_ => External(value.str_ref),
}
}
}
impl From<GffString> for LocString {
fn from(value: GffString) -> Self {
use self::GffString::*;
match value {
External(str_ref) => LocString { str_ref, strings: vec![] },
Internal(strings) => {
let strings = strings.into_iter().map(Into::into).collect();
LocString { str_ref: StrRef(0xFFFFFFFF), strings }
},
}
}
}