use encoding_rs::SHIFT_JIS;
use log::warn;
use serde::{Deserialize, Serialize};
use crate::io::{Error, Result, err};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct MeleeString(pub String);
impl MeleeString {
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn to_normalized(&self) -> String {
self.0.clone().chars().map(fix_char).collect::<String>()
}
pub fn bytes(&self) -> std::borrow::Cow<'_, [u8]> {
let (result, encoding, unmapped) = SHIFT_JIS.encode(&self.0);
assert_eq!(encoding, SHIFT_JIS);
if unmapped {
warn!("unsupported chars in MeleeString: {}", self.0);
}
result
}
}
impl TryFrom<&[u8]> for MeleeString {
type Error = Error;
fn try_from(s: &[u8]) -> Result<MeleeString> {
let first_null = s.iter().position(|&x| x == 0).unwrap_or(s.len());
match SHIFT_JIS.decode_without_bom_handling_and_without_replacement(&s[0..first_null]) {
Some(cow) => Ok(MeleeString(cow.to_string())),
_ => Err(err!("invalid Shift JIS sequence")),
}
}
}
fn fix_char(c: char) -> char {
let c = u32::from(c);
let c = match c {
0xff01..=0xff5e => c + 0x0020 - 0xff00, 0x3000 => 0x20, 0x2019 => 0x27, 0x201d => 0x22, _ => c,
};
char::try_from(c).unwrap()
}