#![doc = svgbobdoc::transform!(
/// <center>
/// ```svgbob
/// ┌────────────────┐
/// │ │
/// ┌────────────►│ CtrStoreData │
/// ┌───────────┐ │ │ │
/// │ │ │ └────────────────┘
/// │ NSD,NCD │ ▼
/// │ ├────────►┌───────────────┐ ┌──────────────┐
/// └────────┬──┘ │ │ │ │
/// ▲ ▼ │ GenericChar │◄──────►│ NxCharInfo │
/// ┌──┴────────┐ │ │ │ │
/// │ ├────────►└───────────────┘ └──────────────┘
/// │ RSD,RCD │ ▲
/// │ │ │ ┌────────────────┐
/// └───────────┘ │ │ │
/// └────────────►│ WsLocalStore │
/// │ │
/// └────────────────┘
/// ```
/// </center>
)]
pub mod ctr;
pub mod generic;
pub mod nx;
pub mod rvl_ntr;
pub use binrw::{BinRead, NullWideString, binrw};
pub use ctr::CtrStoreData;
pub use generic::GenericChar;
pub use nx::NxCharInfo;
pub use rvl_ntr::NtrCharData;
pub use rvl_ntr::NtrStoreData;
pub use rvl_ntr::RvlCharData;
pub use rvl_ntr::RvlStoreData;
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
#[binrw]
#[repr(transparent)]
pub struct FixedLengthWideString<const CHARS: usize>(pub [u16; CHARS]);
impl<const N: usize> std::fmt::Debug for FixedLengthWideString<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "FixedLengthWideString(\"{}\")", self)
}
}
impl<const N: usize> std::fmt::Display for FixedLengthWideString<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.parse_utf16())
}
}
impl<const N: usize> FixedLengthWideString<N> {
fn parse_utf16(self) -> String {
String::from_utf16(&self.0[..])
.expect(
"UTF-16 string parse error. Parsing little endian string on big endian hardware?",
)
.replace("\0", "")
}
}
#[cfg(test)]
mod tests {
use crate::{CtrStoreData, NxCharInfo, RvlCharData, rvl_ntr::FavoriteColor};
use binrw::BinRead;
use std::{error::Error, fs::File};
type R = Result<(), Box<dyn Error>>;
#[test]
fn nx_deser() -> R {
let mut mii = File::open(format!(
"{}/resources_here/j0.charinfo",
std::env::var("CARGO_WORKSPACE_DIR").unwrap()
))?;
let mii = NxCharInfo::read(&mut mii)?;
assert_eq!(mii.nickname.to_string(), "Jo Null".to_string());
assert_eq!(mii.glass_color.0, 17);
assert_eq!(mii.reserved, 0);
Ok(())
}
#[test]
fn ctr_deser() -> R {
let mut mii = File::open(format!(
"{}/resources_here/j0.ffsd",
std::env::var("CARGO_WORKSPACE_DIR").unwrap()
))?;
let mii = CtrStoreData::read(&mut mii)?;
assert_eq!(mii.name.to_string(), "Jo Null".to_string());
assert_eq!(mii.personal_info_2.favorite_color().value(), 8);
Ok(())
}
#[test]
fn rvl_ntr_deser() -> R {
let mut rvl = File::open(format!(
"{}/resources_here/Jain.rcd",
std::env::var("CARGO_WORKSPACE_DIR").unwrap_or(
std::env::current_dir()
.unwrap()
.to_string_lossy()
.to_string()
)
))?;
let rvl = RvlCharData::read(&mut rvl)?;
assert_eq!(rvl.name.to_string(), "Jain".to_string());
let mut ntr = File::open(format!(
"{}/resources_here/Jain.rcd",
std::env::var("CARGO_WORKSPACE_DIR").unwrap_or(
std::env::current_dir()
.unwrap()
.to_string_lossy()
.to_string()
)
))?;
let ntr = RvlCharData::read(&mut ntr)?;
assert_eq!(ntr.name.to_string(), "Jain".to_string());
assert_eq!(ntr.name.to_string(), rvl.name.to_string());
assert_eq!(ntr.personal_info.favorite_color(), FavoriteColor::Purple);
assert_eq!(
ntr.personal_info.favorite_color(),
rvl.personal_info.favorite_color()
);
Ok(())
}
}