From bf66c597994785ed21ca0b19ee1af9a21c883f81 Mon Sep 17 00:00:00 2001 From: G2-Games Date: Tue, 28 May 2024 18:03:35 -0500 Subject: [PATCH] Cleaned up old code, added new functions to `commands.rs` --- Cargo.toml | 2 +- src/netmd/commands.rs | 135 +++- src/netmd/interface.rs | 141 ++-- src/netmd/mappings.rs | 1382 +++++++++++++++++++++++--------------- src/netmd/query_utils.rs | 48 +- src/netmd/utils.rs | 69 +- 6 files changed, 1125 insertions(+), 652 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index efd8f2c..4ce73fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ nofmt = "1.0.0" once_cell = "1.18.0" unicode-normalization = "0.1.22" regex = "1.10.2" -lazy_static = "1.4.0" cross_usb = "0.3" num-derive = "0.3.3" num-traits = "0.2.14" @@ -39,6 +38,7 @@ ecb = "0.1" tokio = { version = "1.36", features = ["sync"] } g2-unicode-jp = "0.4.1" thiserror = "1.0.57" +phf = { version = "0.11.2", features = ["phf_macros", "macros"] } [target.'cfg(target_family = "wasm")'.dependencies] gloo = { version = "0.11.0", features = ["futures"] } diff --git a/src/netmd/commands.rs b/src/netmd/commands.rs index 367378e..3ef459d 100644 --- a/src/netmd/commands.rs +++ b/src/netmd/commands.rs @@ -5,7 +5,10 @@ use std::error::Error; use std::time::Duration; use cross_usb::Descriptor; -use super::interface::{MDSession, MDTrack, NetMDInterface, Direction, InterfaceError}; +use crate::netmd::interface::DiscFlag; +use crate::netmd::utils::RawTime; + +use super::interface::{Channels, Encoding, InterfaceError, MDSession, MDTrack, NetMDInterface, TrackFlag}; use super::utils::cross_sleep; #[derive(FromPrimitive, PartialEq, Eq)] @@ -34,6 +37,66 @@ pub struct DeviceStatus { pub time: Time, } +#[derive(Clone)] +pub struct Track { + index: u16, + title: String, + full_width_title: String, + duration: RawTime, + channel: Channels, + encoding: Encoding, + protected: TrackFlag, +} + +impl Track { + pub fn chars_to_cells(len: usize) -> usize { + f32::ceil(len as f32 / 7.0) as usize + } + + pub async fn cells_for_title(&mut self) { + let encoding_name_correction = match self.encoding { + Encoding::SP => 0, + _ => 1 + }; + + let full_width_length = Self::chars_to_cells(self.full_width_title.len() * 2); + } +} + +pub struct Group { + index: u16, + title: Option, + full_width_title: Option, + tracks: Vec, +} + +pub struct Disc { + title: String, + full_width_title: String, + writeable: bool, + write_protected: bool, + used: u64, + left: u64, + total: u64, + track_count: u16, + groups: Vec, +} + +impl Disc { + pub async fn track_count(&self) -> u16 { + self.groups.iter() + .map(|g| g.tracks.len()) + .reduce(|acc, s| acc + s) + .unwrap() as u16 + } + + pub async fn tracks(&self) -> Vec { + self.groups.iter() + .flat_map(|g| g.tracks.clone()) + .collect() + } +} + pub struct NetMDContext { interface: NetMDInterface, } @@ -48,6 +111,7 @@ impl NetMDContext { }) } + /* /// Change to the next track (skip forward) pub async fn next_track(&mut self) -> Result<(), InterfaceError> { self.interface.track_change(Direction::Next).await @@ -62,6 +126,7 @@ impl NetMDContext { pub async fn restart_track(&mut self) -> Result<(), InterfaceError> { self.interface.track_change(Direction::Restart).await } + */ pub async fn device_status(&mut self) -> Result> { let status = self.interface.status().await?; @@ -132,4 +197,72 @@ impl NetMDContext { Ok(result) } + + pub async fn list_content(&mut self) -> Result> { + let flags = self.interface.disc_flags().await?; + let title = self.interface.disc_title(false).await?; + let full_width_title = self.interface.disc_title(true).await?; + let disc_capacity: [RawTime; 3] = self.interface.disc_capacity().await?; + let track_count = self.interface.track_count().await?; + + let mut frames_used = disc_capacity[0].as_frames(); + let mut frames_total = disc_capacity[1].as_frames(); + let mut frames_left = disc_capacity[2].as_frames(); + + // Some devices report the time remaining of the currently selected recording mode. (Sharps) + while frames_total > 512 * 60 * 82 { + frames_used /= 2; + frames_total /= 2; + frames_left /= 2; + } + + let track_group_list = self.interface.track_group_list().await?; + + let mut groups = vec![]; + for (index, group) in track_group_list.iter().enumerate() { + let mut tracks = vec![]; + for track in &group.2 { + let (encoding, channel) = self.interface.track_encoding(*track).await?; + let duration = self.interface.track_length(*track).await?; + let flags = self.interface.track_flags(*track).await?; + let title = self.interface.track_title(*track, false).await?; + let full_width_title = self.interface.track_title(*track, true).await?; + + tracks.push( + Track { + index: *track, + title, + full_width_title, + duration, + channel, + encoding, + protected: TrackFlag::from_u8(flags).unwrap(), + } + ) + } + + groups.push( + Group { + index: index as u16, + title: group.0.clone(), + full_width_title: group.1.clone(), + tracks + } + ) + } + + let disc = Disc { + title, + full_width_title, + writeable: (flags & DiscFlag::Writable as u8) != 0, + write_protected: (flags & DiscFlag::WriteProtected as u8) != 0, + used: frames_used, + left: frames_left, + total: frames_total, + track_count, + groups + }; + + Ok(disc) + } } diff --git a/src/netmd/interface.rs b/src/netmd/interface.rs index 0a333db..e11dd4d 100644 --- a/src/netmd/interface.rs +++ b/src/netmd/interface.rs @@ -2,8 +2,9 @@ use crate::netmd::base; use crate::netmd::query_utils::{format_query, scan_query, QueryValue}; use crate::netmd::utils::{ - half_width_to_full_width_range, length_after_encoding_to_jis, sanitize_full_width_title, - sanitize_half_width_title, time_to_duration, + half_width_to_full_width_range, length_after_encoding_to_sjis, sanitize_full_width_title, + sanitize_half_width_title, + RawTime, }; use cbc::cipher::block_padding::NoPadding; use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyInit, KeyIvInit}; @@ -16,8 +17,6 @@ use thiserror::Error; use std::error::Error; use tokio::sync::mpsc::UnboundedReceiver; -use lazy_static::lazy_static; - use super::base::NetMD; use super::utils::cross_sleep; @@ -52,7 +51,7 @@ pub enum WireFormat { } impl WireFormat { - fn frame_size(&self) -> u16 { + const fn frame_size(&self) -> u16 { match self { WireFormat::Pcm => 2048, WireFormat::L105kbps => 192, @@ -60,31 +59,70 @@ impl WireFormat { WireFormat::LP4 => 96, } } + + const fn disc_for_wire(&self) -> DiscFormat { + match self { + WireFormat::Pcm => DiscFormat::SPStereo, + WireFormat::L105kbps => DiscFormat::LP2, + WireFormat::LP2 => DiscFormat::LP2, + WireFormat::LP4 => DiscFormat::LP4, + } + } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Encoding { SP = 0x90, LP2 = 0x92, LP4 = 0x93, } -enum Channels { +impl ToString for Encoding { + fn to_string(&self) -> String { + match self { + Encoding::SP => String::from("sp"), + Encoding::LP2 => String::from("lp2"), + Encoding::LP4 => String::from("lp4"), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum Channels { Mono = 0x01, Stereo = 0x00, } +impl ToString for Channels { + fn to_string(&self) -> String { + match self { + Channels::Mono => String::from("mono"), + Channels::Stereo => String::from("stereo"), + } + } +} + enum ChannelCount { Mono = 1, Stereo = 2, } -enum TrackFlag { +#[derive(Debug, Clone, Copy, FromPrimitive)] +pub enum TrackFlag { Protected = 0x03, Unprotected = 0x00, } -enum DiscFlag { +impl ToString for TrackFlag { + fn to_string(&self) -> String { + match self { + TrackFlag::Protected => String::from("protected"), + TrackFlag::Unprotected => String::from("unprotected"), + } + } +} + +pub enum DiscFlag { Writable = 0x10, WriteProtected = 0x40, } @@ -161,15 +199,6 @@ enum NetmdStatus { Interim = 0x0f, } -lazy_static! { - static ref FRAME_SIZE: HashMap = HashMap::from([ - (WireFormat::Pcm, 2048), - (WireFormat::LP2, 192), - (WireFormat::L105kbps, 152), - (WireFormat::LP4, 96), - ]); -} - #[derive(Error, Debug, Eq, PartialEq, PartialOrd, Ord)] #[error("invalid status code")] pub struct StatusError; @@ -1065,7 +1094,7 @@ impl NetMDInterface { } let new_title: Vec; - let old_len = length_after_encoding_to_jis(¤t_title); + let old_len = length_after_encoding_to_sjis(¤t_title); let wchar_value = match wchar { true => { @@ -1143,7 +1172,7 @@ impl NetMDInterface { if title == current_title { return Ok(()); } - length_after_encoding_to_jis(¤t_title) as u16 + length_after_encoding_to_sjis(¤t_title) as u16 } Err(error) if error.to_string() == "Rejected" => 0, Err(error) => return Err(error), @@ -1232,12 +1261,12 @@ impl NetMDInterface { Ok(res[0].to_vec().unwrap()) } - /// Gets the length of tracks as a [std::time::Duration] from a set + /// Gets the length of tracks as a raw duration from a set pub async fn track_lengths( &mut self, tracks: Vec, - ) -> Result, InterfaceError> { - let mut times: Vec = vec![]; + ) -> Result, InterfaceError> { + let mut times = vec![]; self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead) .await?; @@ -1269,8 +1298,12 @@ impl NetMDInterface { .map(|v| v.to_i64().unwrap() as u64) .collect(); - let length = time_to_duration(×_num); - times.push(length); + times.push(RawTime { + hours: times_num[0], + minutes: times_num[1], + seconds: times_num[2], + frames: times_num[3], + }); } self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::Close) @@ -1279,20 +1312,20 @@ impl NetMDInterface { Ok(times) } - /// Gets the length of a track as a [std::time::Duration] + /// Gets the length of a track as a raw duration pub async fn track_length( &mut self, track: u16, - ) -> Result { + ) -> Result { Ok(self.track_lengths([track].into()).await?[0]) } /// Gets the encoding of a track (SP, LP2, LP4) - pub async fn track_encoding(&mut self, track_number: u16) -> Result { + pub async fn track_encoding(&mut self, track_number: u16) -> Result<(Encoding, Channels), InterfaceError> { let raw_value = self.raw_track_info(track_number, 0x3080, 0x0700).await?; let result = scan_query(raw_value, "07 0004 0110 %b %b".to_string())?; - let final_encoding = match result[0].to_i64() { + let encoding = match result[0].to_i64() { Ok(0x90) => Encoding::SP, Ok(0x92) => Encoding::LP2, Ok(0x93) => Encoding::LP4, @@ -1300,7 +1333,14 @@ impl NetMDInterface { Err(_) => unreachable!(), }; - Ok(final_encoding) + let channels = match result[0].to_i64() { + Ok(0x01) => Channels::Stereo, + Ok(0x00) => Channels::Mono, + Ok(e) => return Err(InterfaceError::InvalidEncoding(e as u8)), + Err(_) => unreachable!(), + }; + + Ok((encoding, channels)) } /// Gets a track's flags @@ -1323,36 +1363,34 @@ impl NetMDInterface { } /// Gets the disc capacity as a [std::time::Duration] - pub async fn disc_capacity(&mut self) -> Result<[std::time::Duration; 3], InterfaceError> { + pub async fn disc_capacity(&mut self) -> Result<[RawTime; 3], InterfaceError> { self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead) .await?; let mut query = format_query("1806 02101000 3080 0300 ff00 00000000".to_string(), vec![])?; let reply = self.send_query(&mut query, false, false).await?; - let mut result: [std::time::Duration; 3] = [std::time::Duration::from_secs(0); 3]; // 8003 changed to %?03 - Panasonic returns 0803 instead. This byte's meaning is unknown let res = scan_query( reply, "1806 02101000 3080 0300 1000 001d0000 001b %?03 0017 8000 0005 %W %B %B %B 0005 %W %B %B %B 0005 %W %B %B %B".to_string() - )?; //25^ - let res_num: Vec = res - .into_iter() - .map(|v| v.to_i64().unwrap() as u64) - .collect(); + )?; - // Create 3 values, `Frames Used`, `Frames Total`, and `Frames Left` - for i in 0..3 { - let tmp = &res_num[(4 * i)..=(4 * i) + 3]; - let time_micros = - (tmp[0] * 3600000000) + (tmp[1] * 60000000) + (tmp[2] * 1000000) + (tmp[3] * 11600); - result[i] = std::time::Duration::from_micros(time_micros); - } + let res_num: Vec = res + .windows(4) + .step_by(4) + .map(|t| RawTime { + hours: t[0].to_i64().unwrap() as u64, + minutes: t[1].to_i64().unwrap() as u64, + seconds: t[2].to_i64().unwrap() as u64, + frames: t[3].to_i64().unwrap() as u64, + }) + .collect(); self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::Close) .await?; - Ok(result) + Ok(res_num.try_into().unwrap()) } pub async fn recording_parameters(&mut self) -> Result, InterfaceError> { @@ -1724,15 +1762,6 @@ pub fn retailmac(key: &[u8], value: &[u8], iv: &[u8; 8]) -> Vec { end[..8].to_vec() } -lazy_static! { - static ref DISC_FOR_WIRE: HashMap = HashMap::from([ - (WireFormat::Pcm, DiscFormat::SPStereo), - (WireFormat::LP2, DiscFormat::LP2), - (WireFormat::L105kbps, DiscFormat::LP2), - (WireFormat::LP4, DiscFormat::LP4), - ]); -} - pub struct EKBData { chains: [[u8; 16]; 2], depth: i32, @@ -1811,7 +1840,7 @@ impl MDTrack { } pub fn frame_size(&self) -> usize { - *FRAME_SIZE.get(&self.format).unwrap() + self.format.frame_size() as usize } pub fn chunk_size(&self) -> usize { @@ -1907,7 +1936,7 @@ impl<'a> MDSession<'a> { ) .await?; let data_format = track.data_format(); - let final_disc_format = disc_format.unwrap_or(*DISC_FOR_WIRE.get(&data_format).unwrap()); + let final_disc_format = disc_format.unwrap_or(data_format.disc_for_wire()); let (track_index, uuid, ccid) = self .md diff --git a/src/netmd/mappings.rs b/src/netmd/mappings.rs index 6dec72a..6ce22aa 100644 --- a/src/netmd/mappings.rs +++ b/src/netmd/mappings.rs @@ -1,554 +1,830 @@ -use lazy_static::lazy_static; -use std::collections::HashMap; +use phf::phf_map; -lazy_static! { - pub static ref MAPPINGS_JP: HashMap = HashMap::from([ - ("!".to_string(), "!".to_string()), - ("\"".to_string(), """.to_string()), - ("#".to_string(), "#".to_string()), - ("$".to_string(), "$".to_string()), - ("%".to_string(), "%".to_string()), - ("&".to_string(), "&".to_string()), - ("'".to_string(), "'".to_string()), - ("(".to_string(), "(".to_string()), - (")".to_string(), ")".to_string()), - ("*".to_string(), "*".to_string()), - ("+".to_string(), "+".to_string()), - (",".to_string(), ",".to_string()), - ("-".to_string(), "-".to_string()), - (".".to_string(), ".".to_string()), - ("/".to_string(), "/".to_string()), - (":".to_string(), ":".to_string()), - (";".to_string(), ";".to_string()), - ("<".to_string(), "<".to_string()), - ("=".to_string(), "=".to_string()), - (">".to_string(), ">".to_string()), - ("?".to_string(), "?".to_string()), - ("@".to_string(), "@".to_string()), - ("A".to_string(), "A".to_string()), - ("B".to_string(), "B".to_string()), - ("C".to_string(), "C".to_string()), - ("D".to_string(), "D".to_string()), - ("E".to_string(), "E".to_string()), - ("F".to_string(), "F".to_string()), - ("G".to_string(), "G".to_string()), - ("H".to_string(), "H".to_string()), - ("I".to_string(), "I".to_string()), - ("J".to_string(), "J".to_string()), - ("K".to_string(), "K".to_string()), - ("L".to_string(), "L".to_string()), - ("M".to_string(), "M".to_string()), - ("N".to_string(), "N".to_string()), - ("O".to_string(), "O".to_string()), - ("P".to_string(), "P".to_string()), - ("Q".to_string(), "Q".to_string()), - ("R".to_string(), "R".to_string()), - ("S".to_string(), "S".to_string()), - ("T".to_string(), "T".to_string()), - ("U".to_string(), "U".to_string()), - ("V".to_string(), "V".to_string()), - ("W".to_string(), "W".to_string()), - ("X".to_string(), "X".to_string()), - ("Y".to_string(), "Y".to_string()), - ("Z".to_string(), "Z".to_string()), - ("[".to_string(), "[".to_string()), - ("\\".to_string(), "\".to_string()), - ("]".to_string(), "]".to_string()), - ("^".to_string(), "^".to_string()), - ("_".to_string(), "_".to_string()), - ("`".to_string(), "`".to_string()), - ("a".to_string(), "a".to_string()), - ("b".to_string(), "b".to_string()), - ("c".to_string(), "c".to_string()), - ("d".to_string(), "d".to_string()), - ("e".to_string(), "e".to_string()), - ("f".to_string(), "f".to_string()), - ("g".to_string(), "g".to_string()), - ("h".to_string(), "h".to_string()), - ("i".to_string(), "i".to_string()), - ("j".to_string(), "j".to_string()), - ("k".to_string(), "k".to_string()), - ("l".to_string(), "l".to_string()), - ("m".to_string(), "m".to_string()), - ("n".to_string(), "n".to_string()), - ("o".to_string(), "o".to_string()), - ("p".to_string(), "p".to_string()), - ("q".to_string(), "q".to_string()), - ("r".to_string(), "r".to_string()), - ("s".to_string(), "s".to_string()), - ("t".to_string(), "t".to_string()), - ("u".to_string(), "u".to_string()), - ("v".to_string(), "v".to_string()), - ("w".to_string(), "w".to_string()), - ("x".to_string(), "x".to_string()), - ("y".to_string(), "y".to_string()), - ("z".to_string(), "z".to_string()), - ("{".to_string(), "{".to_string()), - ("|".to_string(), "|".to_string()), - ("}".to_string(), "}".to_string()), - ("~".to_string(), "~".to_string()), - (" ".to_string(), "\u{3000}".to_string()), - ("0".to_string(), "0".to_string()), - ("1".to_string(), "1".to_string()), - ("2".to_string(), "2".to_string()), - ("3".to_string(), "3".to_string()), - ("4".to_string(), "4".to_string()), - ("5".to_string(), "5".to_string()), - ("6".to_string(), "6".to_string()), - ("7".to_string(), "7".to_string()), - ("8".to_string(), "8".to_string()), - ("9".to_string(), "9".to_string()), - ("ァ".to_string(), "ァ".to_string()), - ("ア".to_string(), "ア".to_string()), - ("ィ".to_string(), "ィ".to_string()), - ("イ".to_string(), "イ".to_string()), - ("ゥ".to_string(), "ゥ".to_string()), - ("ウ".to_string(), "ウ".to_string()), - ("ェ".to_string(), "ェ".to_string()), - ("エ".to_string(), "エ".to_string()), - ("ォ".to_string(), "ォ".to_string()), - ("オ".to_string(), "オ".to_string()), - ("カ".to_string(), "カ".to_string()), - ("ガ".to_string(), "ガ".to_string()), - ("キ".to_string(), "キ".to_string()), - ("ギ".to_string(), "ギ".to_string()), - ("ク".to_string(), "ク".to_string()), - ("グ".to_string(), "グ".to_string()), - ("ケ".to_string(), "ケ".to_string()), - ("ゲ".to_string(), "ゲ".to_string()), - ("コ".to_string(), "コ".to_string()), - ("ゴ".to_string(), "ゴ".to_string()), - ("サ".to_string(), "サ".to_string()), - ("ザ".to_string(), "ザ".to_string()), - ("シ".to_string(), "シ".to_string()), - ("ジ".to_string(), "ジ".to_string()), - ("ス".to_string(), "ス".to_string()), - ("ズ".to_string(), "ズ".to_string()), - ("セ".to_string(), "セ".to_string()), - ("ゼ".to_string(), "ゼ".to_string()), - ("ソ".to_string(), "ソ".to_string()), - ("ゾ".to_string(), "ゾ".to_string()), - ("タ".to_string(), "タ".to_string()), - ("ダ".to_string(), "ダ".to_string()), - ("チ".to_string(), "チ".to_string()), - ("ヂ".to_string(), "ヂ".to_string()), - ("ッ".to_string(), "ッ".to_string()), - ("ツ".to_string(), "ツ".to_string()), - ("ヅ".to_string(), "ヅ".to_string()), - ("テ".to_string(), "テ".to_string()), - ("デ".to_string(), "デ".to_string()), - ("ト".to_string(), "ト".to_string()), - ("ド".to_string(), "ド".to_string()), - ("ナ".to_string(), "ナ".to_string()), - ("ニ".to_string(), "ニ".to_string()), - ("ヌ".to_string(), "ヌ".to_string()), - ("ネ".to_string(), "ネ".to_string()), - ("ノ".to_string(), "ノ".to_string()), - ("ハ".to_string(), "ハ".to_string()), - ("バ".to_string(), "バ".to_string()), - ("パ".to_string(), "パ".to_string()), - ("ヒ".to_string(), "ヒ".to_string()), - ("ビ".to_string(), "ビ".to_string()), - ("ピ".to_string(), "ピ".to_string()), - ("フ".to_string(), "フ".to_string()), - ("ブ".to_string(), "ブ".to_string()), - ("プ".to_string(), "プ".to_string()), - ("ヘ".to_string(), "ヘ".to_string()), - ("ベ".to_string(), "ベ".to_string()), - ("ペ".to_string(), "ペ".to_string()), - ("ホ".to_string(), "ホ".to_string()), - ("ボ".to_string(), "ボ".to_string()), - ("ポ".to_string(), "ポ".to_string()), - ("マ".to_string(), "マ".to_string()), - ("ミ".to_string(), "ミ".to_string()), - ("ム".to_string(), "ム".to_string()), - ("メ".to_string(), "メ".to_string()), - ("モ".to_string(), "モ".to_string()), - ("ャ".to_string(), "ャ".to_string()), - ("ヤ".to_string(), "ヤ".to_string()), - ("ュ".to_string(), "ュ".to_string()), - ("ユ".to_string(), "ユ".to_string()), - ("ョ".to_string(), "ョ".to_string()), - ("ヨ".to_string(), "ヨ".to_string()), - ("ラ".to_string(), "ラ".to_string()), - ("リ".to_string(), "リ".to_string()), - ("ル".to_string(), "ル".to_string()), - ("レ".to_string(), "レ".to_string()), - ("ロ".to_string(), "ロ".to_string()), - ("ワ".to_string(), "ワ".to_string()), - ("ヲ".to_string(), "ヲ".to_string()), - ("ン".to_string(), "ン".to_string()), - ("ー".to_string(), "ー".to_string()), - ("ヮ".to_string(), "ヮ".to_string()), - ("ヰ".to_string(), "ヰ".to_string()), - ("ヱ".to_string(), "ヱ".to_string()), - ("ヵ".to_string(), "ヵ".to_string()), - ("ヶ".to_string(), "ヶ".to_string()), - ("ヴ".to_string(), "ヴ".to_string()), - ("ヽ".to_string(), "ヽ".to_string()), - ("ヾ".to_string(), "ヾ".to_string()), - ("・".to_string(), "・".to_string()), - ("「".to_string(), "「".to_string()), - ("」".to_string(), "」".to_string()), - ("。".to_string(), "。".to_string()), - ("、".to_string(), "、".to_string()) - ]); - pub static ref MAPPINGS_RU: HashMap = HashMap::from([ - ("а".to_string(), "a".to_string()), - ("б".to_string(), "b".to_string()), - ("в".to_string(), "v".to_string()), - ("г".to_string(), "g".to_string()), - ("д".to_string(), "d".to_string()), - ("е".to_string(), "e".to_string()), - ("ё".to_string(), "e".to_string()), - ("ж".to_string(), "zh".to_string()), - ("з".to_string(), "z".to_string()), - ("и".to_string(), "i".to_string()), - ("й".to_string(), "i".to_string()), - ("к".to_string(), "k".to_string()), - ("л".to_string(), "l".to_string()), - ("м".to_string(), "m".to_string()), - ("н".to_string(), "n".to_string()), - ("о".to_string(), "o".to_string()), - ("п".to_string(), "p".to_string()), - ("р".to_string(), "r".to_string()), - ("с".to_string(), "s".to_string()), - ("т".to_string(), "t".to_string()), - ("у".to_string(), "u".to_string()), - ("ф".to_string(), "f".to_string()), - ("х".to_string(), "kh".to_string()), - ("ц".to_string(), "tc".to_string()), - ("ч".to_string(), "ch".to_string()), - ("ш".to_string(), "sh".to_string()), - ("щ".to_string(), "shch".to_string()), - ("ъ".to_string(), "".to_string()), - ("ы".to_string(), "y".to_string()), - ("ь".to_string(), "'".to_string()), - ("э".to_string(), "e".to_string()), - ("ю".to_string(), "iu".to_string()), - ("я".to_string(), "ia".to_string()), - ("А".to_string(), "A".to_string()), - ("Б".to_string(), "B".to_string()), - ("В".to_string(), "V".to_string()), - ("Г".to_string(), "G".to_string()), - ("Д".to_string(), "D".to_string()), - ("Е".to_string(), "E".to_string()), - ("Ё".to_string(), "E".to_string()), - ("Ж".to_string(), "Zh".to_string()), - ("З".to_string(), "Z".to_string()), - ("И".to_string(), "I".to_string()), - ("Й".to_string(), "I".to_string()), - ("К".to_string(), "K".to_string()), - ("Л".to_string(), "L".to_string()), - ("М".to_string(), "M".to_string()), - ("Н".to_string(), "N".to_string()), - ("О".to_string(), "O".to_string()), - ("П".to_string(), "P".to_string()), - ("Р".to_string(), "R".to_string()), - ("С".to_string(), "S".to_string()), - ("Т".to_string(), "T".to_string()), - ("У".to_string(), "U".to_string()), - ("Ф".to_string(), "F".to_string()), - ("Х".to_string(), "Kh".to_string()), - ("Ц".to_string(), "Tc".to_string()), - ("Ч".to_string(), "Ch".to_string()), - ("Ш".to_string(), "Sh".to_string()), - ("Щ".to_string(), "Shch".to_string()), - ("Ъ".to_string(), "".to_string()), - ("Ы".to_string(), "Y".to_string()), - ("Ь".to_string(), "'".to_string()), - ("Э".to_string(), "E".to_string()), - ("Ю".to_string(), "Iu".to_string()), - ("Я".to_string(), "Ia".to_string()) - ]); - pub static ref MAPPINGS_DE: HashMap = HashMap::from([ - ("Ä".to_string(), "Ae".to_string()), - ("ä".to_string(), "ae".to_string()), - ("Ö".to_string(), "Oe".to_string()), - ("ö".to_string(), "oe".to_string()), - ("Ü".to_string(), "Ue".to_string()), - ("ü".to_string(), "ue".to_string()), - ("ß".to_string(), "ss".to_string()) - ]); - pub static ref MAPPINGS_HW: HashMap = HashMap::from([ - ("-".to_string(), "-".to_string()), - ("ー".to_string(), "-".to_string()), - ("ァ".to_string(), "ァ".to_string()), - ("ア".to_string(), "ア".to_string()), - ("ィ".to_string(), "ィ".to_string()), - ("イ".to_string(), "イ".to_string()), - ("ゥ".to_string(), "ゥ".to_string()), - ("ウ".to_string(), "ウ".to_string()), - ("ェ".to_string(), "ェ".to_string()), - ("エ".to_string(), "エ".to_string()), - ("ォ".to_string(), "ォ".to_string()), - ("オ".to_string(), "オ".to_string()), - ("カ".to_string(), "カ".to_string()), - ("ガ".to_string(), "ガ".to_string()), - ("キ".to_string(), "キ".to_string()), - ("ギ".to_string(), "ギ".to_string()), - ("ク".to_string(), "ク".to_string()), - ("グ".to_string(), "グ".to_string()), - ("ケ".to_string(), "ケ".to_string()), - ("ゲ".to_string(), "ゲ".to_string()), - ("コ".to_string(), "コ".to_string()), - ("ゴ".to_string(), "ゴ".to_string()), - ("サ".to_string(), "サ".to_string()), - ("ザ".to_string(), "ザ".to_string()), - ("シ".to_string(), "シ".to_string()), - ("ジ".to_string(), "ジ".to_string()), - ("ス".to_string(), "ス".to_string()), - ("ズ".to_string(), "ズ".to_string()), - ("セ".to_string(), "セ".to_string()), - ("ゼ".to_string(), "ゼ".to_string()), - ("ソ".to_string(), "ソ".to_string()), - ("ゾ".to_string(), "ゾ".to_string()), - ("タ".to_string(), "タ".to_string()), - ("ダ".to_string(), "ダ".to_string()), - ("チ".to_string(), "チ".to_string()), - ("ヂ".to_string(), "ヂ".to_string()), - ("ッ".to_string(), "ッ".to_string()), - ("ツ".to_string(), "ツ".to_string()), - ("ヅ".to_string(), "ヅ".to_string()), - ("テ".to_string(), "テ".to_string()), - ("デ".to_string(), "デ".to_string()), - ("ト".to_string(), "ト".to_string()), - ("ド".to_string(), "ド".to_string()), - ("ナ".to_string(), "ナ".to_string()), - ("ニ".to_string(), "ニ".to_string()), - ("ヌ".to_string(), "ヌ".to_string()), - ("ネ".to_string(), "ネ".to_string()), - ("ノ".to_string(), "ノ".to_string()), - ("ハ".to_string(), "ハ".to_string()), - ("バ".to_string(), "バ".to_string()), - ("パ".to_string(), "パ".to_string()), - ("ヒ".to_string(), "ヒ".to_string()), - ("ビ".to_string(), "ビ".to_string()), - ("ピ".to_string(), "ピ".to_string()), - ("フ".to_string(), "フ".to_string()), - ("ブ".to_string(), "ブ".to_string()), - ("プ".to_string(), "プ".to_string()), - ("ヘ".to_string(), "ヘ".to_string()), - ("ベ".to_string(), "ベ".to_string()), - ("ペ".to_string(), "ペ".to_string()), - ("ホ".to_string(), "ホ".to_string()), - ("ボ".to_string(), "ボ".to_string()), - ("ポ".to_string(), "ポ".to_string()), - ("マ".to_string(), "マ".to_string()), - ("ミ".to_string(), "ミ".to_string()), - ("ム".to_string(), "ム".to_string()), - ("メ".to_string(), "メ".to_string()), - ("モ".to_string(), "モ".to_string()), - ("ャ".to_string(), "ャ".to_string()), - ("ヤ".to_string(), "ヤ".to_string()), - ("ュ".to_string(), "ュ".to_string()), - ("ユ".to_string(), "ユ".to_string()), - ("ョ".to_string(), "ョ".to_string()), - ("ヨ".to_string(), "ヨ".to_string()), - ("ラ".to_string(), "ラ".to_string()), - ("リ".to_string(), "リ".to_string()), - ("ル".to_string(), "ル".to_string()), - ("レ".to_string(), "レ".to_string()), - ("ロ".to_string(), "ロ".to_string()), - ("ワ".to_string(), "ワ".to_string()), - ("ヲ".to_string(), "ヲ".to_string()), - ("ン".to_string(), "ン".to_string()), - ("ー".to_string(), "-".to_string()), - ("ヮ".to_string(), "ヮ".to_string()), - ("ヰ".to_string(), "ヰ".to_string()), - ("ヱ".to_string(), "ヱ".to_string()), - ("ヵ".to_string(), "ヵ".to_string()), - ("ヶ".to_string(), "ヶ".to_string()), - ("ヴ".to_string(), "ヴ".to_string()), - ("ヽ".to_string(), "ヽ".to_string()), - ("ヾ".to_string(), "ヾ".to_string()), - ("・".to_string(), "・".to_string()), - ("「".to_string(), "「".to_string()), - ("」".to_string(), "」".to_string()), - ("。".to_string(), "。".to_string()), - ("、".to_string(), "、".to_string()), - ("!".to_string(), "!".to_string()), - (""".to_string(), "\"".to_string()), - ("#".to_string(), "#".to_string()), - ("$".to_string(), "$".to_string()), - ("%".to_string(), "%".to_string()), - ("&".to_string(), "&".to_string()), - ("'".to_string(), "'".to_string()), - ("(".to_string(), "(".to_string()), - (")".to_string(), ")".to_string()), - ("*".to_string(), "*".to_string()), - ("+".to_string(), "+".to_string()), - (",".to_string(), ",".to_string()), - (".".to_string(), ".".to_string()), - ("/".to_string(), "/".to_string()), - (":".to_string(), ":".to_string()), - (";".to_string(), ";".to_string()), - ("<".to_string(), "<".to_string()), - ("=".to_string(), "=".to_string()), - (">".to_string(), ">".to_string()), - ("?".to_string(), "?".to_string()), - ("@".to_string(), "@".to_string()), - ("A".to_string(), "A".to_string()), - ("B".to_string(), "B".to_string()), - ("C".to_string(), "C".to_string()), - ("D".to_string(), "D".to_string()), - ("E".to_string(), "E".to_string()), - ("F".to_string(), "F".to_string()), - ("G".to_string(), "G".to_string()), - ("H".to_string(), "H".to_string()), - ("I".to_string(), "I".to_string()), - ("J".to_string(), "J".to_string()), - ("K".to_string(), "K".to_string()), - ("L".to_string(), "L".to_string()), - ("M".to_string(), "M".to_string()), - ("N".to_string(), "N".to_string()), - ("O".to_string(), "O".to_string()), - ("P".to_string(), "P".to_string()), - ("Q".to_string(), "Q".to_string()), - ("R".to_string(), "R".to_string()), - ("S".to_string(), "S".to_string()), - ("T".to_string(), "T".to_string()), - ("U".to_string(), "U".to_string()), - ("V".to_string(), "V".to_string()), - ("W".to_string(), "W".to_string()), - ("X".to_string(), "X".to_string()), - ("Y".to_string(), "Y".to_string()), - ("Z".to_string(), "Z".to_string()), - ("[".to_string(), "[".to_string()), - ("\".to_string(), "\\".to_string()), - ("]".to_string(), "]".to_string()), - ("^".to_string(), "^".to_string()), - ("_".to_string(), "_".to_string()), - ("`".to_string(), "`".to_string()), - ("a".to_string(), "a".to_string()), - ("b".to_string(), "b".to_string()), - ("c".to_string(), "c".to_string()), - ("d".to_string(), "d".to_string()), - ("e".to_string(), "e".to_string()), - ("f".to_string(), "f".to_string()), - ("g".to_string(), "g".to_string()), - ("h".to_string(), "h".to_string()), - ("i".to_string(), "i".to_string()), - ("j".to_string(), "j".to_string()), - ("k".to_string(), "k".to_string()), - ("l".to_string(), "l".to_string()), - ("m".to_string(), "m".to_string()), - ("n".to_string(), "n".to_string()), - ("o".to_string(), "o".to_string()), - ("p".to_string(), "p".to_string()), - ("q".to_string(), "q".to_string()), - ("r".to_string(), "r".to_string()), - ("s".to_string(), "s".to_string()), - ("t".to_string(), "t".to_string()), - ("u".to_string(), "u".to_string()), - ("v".to_string(), "v".to_string()), - ("w".to_string(), "w".to_string()), - ("x".to_string(), "x".to_string()), - ("y".to_string(), "y".to_string()), - ("z".to_string(), "z".to_string()), - ("{".to_string(), "{".to_string()), - ("|".to_string(), "|".to_string()), - ("}".to_string(), "}".to_string()), - ("~".to_string(), "~".to_string()), - (" ".to_string(), " ".to_string()), - ("0".to_string(), "0".to_string()), - ("1".to_string(), "1".to_string()), - ("2".to_string(), "2".to_string()), - ("3".to_string(), "3".to_string()), - ("4".to_string(), "4".to_string()), - ("5".to_string(), "5".to_string()), - ("6".to_string(), "6".to_string()), - ("7".to_string(), "7".to_string()), - ("8".to_string(), "8".to_string()), - ("9".to_string(), "9".to_string()), - ("ぁ".to_string(), "ァ".to_string()), - ("あ".to_string(), "ア".to_string()), - ("ぃ".to_string(), "ィ".to_string()), - ("い".to_string(), "イ".to_string()), - ("ぅ".to_string(), "ゥ".to_string()), - ("う".to_string(), "ウ".to_string()), - ("ぇ".to_string(), "ェ".to_string()), - ("え".to_string(), "エ".to_string()), - ("ぉ".to_string(), "ォ".to_string()), - ("お".to_string(), "オ".to_string()), - ("か".to_string(), "カ".to_string()), - ("が".to_string(), "ガ".to_string()), - ("き".to_string(), "キ".to_string()), - ("ぎ".to_string(), "ギ".to_string()), - ("く".to_string(), "ク".to_string()), - ("ぐ".to_string(), "グ".to_string()), - ("け".to_string(), "ケ".to_string()), - ("げ".to_string(), "ゲ".to_string()), - ("こ".to_string(), "コ".to_string()), - ("ご".to_string(), "ゴ".to_string()), - ("さ".to_string(), "サ".to_string()), - ("ざ".to_string(), "ザ".to_string()), - ("し".to_string(), "シ".to_string()), - ("じ".to_string(), "ジ".to_string()), - ("す".to_string(), "ス".to_string()), - ("ず".to_string(), "ズ".to_string()), - ("せ".to_string(), "セ".to_string()), - ("ぜ".to_string(), "ゼ".to_string()), - ("そ".to_string(), "ソ".to_string()), - ("ぞ".to_string(), "ゾ".to_string()), - ("た".to_string(), "タ".to_string()), - ("だ".to_string(), "ダ".to_string()), - ("ち".to_string(), "チ".to_string()), - ("ぢ".to_string(), "ヂ".to_string()), - ("っ".to_string(), "ッ".to_string()), - ("つ".to_string(), "ツ".to_string()), - ("づ".to_string(), "ヅ".to_string()), - ("て".to_string(), "テ".to_string()), - ("で".to_string(), "デ".to_string()), - ("と".to_string(), "ト".to_string()), - ("ど".to_string(), "ド".to_string()), - ("な".to_string(), "ナ".to_string()), - ("に".to_string(), "ニ".to_string()), - ("ぬ".to_string(), "ヌ".to_string()), - ("ね".to_string(), "ネ".to_string()), - ("の".to_string(), "ノ".to_string()), - ("は".to_string(), "ハ".to_string()), - ("ば".to_string(), "バ".to_string()), - ("ぱ".to_string(), "パ".to_string()), - ("ひ".to_string(), "ヒ".to_string()), - ("び".to_string(), "ビ".to_string()), - ("ぴ".to_string(), "ピ".to_string()), - ("ふ".to_string(), "フ".to_string()), - ("ぶ".to_string(), "ブ".to_string()), - ("ぷ".to_string(), "プ".to_string()), - ("へ".to_string(), "ヘ".to_string()), - ("べ".to_string(), "ベ".to_string()), - ("ぺ".to_string(), "ペ".to_string()), - ("ほ".to_string(), "ホ".to_string()), - ("ぼ".to_string(), "ボ".to_string()), - ("ぽ".to_string(), "ポ".to_string()), - ("ま".to_string(), "マ".to_string()), - ("み".to_string(), "ミ".to_string()), - ("む".to_string(), "ム".to_string()), - ("め".to_string(), "メ".to_string()), - ("も".to_string(), "モ".to_string()), - ("ゃ".to_string(), "ャ".to_string()), - ("や".to_string(), "ヤ".to_string()), - ("ゅ".to_string(), "ュ".to_string()), - ("ゆ".to_string(), "ユ".to_string()), - ("ょ".to_string(), "ョ".to_string()), - ("よ".to_string(), "ヨ".to_string()), - ("ら".to_string(), "ラ".to_string()), - ("り".to_string(), "リ".to_string()), - ("る".to_string(), "ル".to_string()), - ("れ".to_string(), "レ".to_string()), - ("ろ".to_string(), "ロ".to_string()), - ("わ".to_string(), "ワ".to_string()), - ("を".to_string(), "ヲ".to_string()), - ("ん".to_string(), "ン".to_string()), - ("ゎ".to_string(), "ヮ".to_string()), - ("ゐ".to_string(), "ヰ".to_string()), - ("ゑ".to_string(), "ヱ".to_string()), - ("ゕ".to_string(), "ヵ".to_string()), - ("ゖ".to_string(), "ヶ".to_string()), - ("ゔ".to_string(), "ヴ".to_string()), - ("ゝ".to_string(), "ヽ".to_string()), - ("ゞ".to_string(), "ヾ".to_string()), - ]); - pub static ref ALLOWED_HW_KANA: Vec = MAPPINGS_HW.values().cloned().collect(); -} +pub static MAPPINGS_JP: phf::Map<&'static str, &'static str> = phf_map!{ + "!" =>"!", + "\"" =>""", + "#" =>"#", + "$" =>"$", + "%" =>"%", + "&" =>"&", + "'" =>"'", + "" =>"(", + ")" =>")", + "*" =>"*", + "+" =>"+", + "," =>",", + "-" =>"-", + "." =>".", + "/" =>"/", + ":" =>":", + ";" =>";", + "<" =>"<", + "=" =>"=", + ">" =>">", + "?" =>"?", + "@" =>"@", + "A" =>"A", + "B" =>"B", + "C" =>"C", + "D" =>"D", + "E" =>"E", + "F" =>"F", + "G" =>"G", + "H" =>"H", + "I" =>"I", + "J" =>"J", + "K" =>"K", + "L" =>"L", + "M" =>"M", + "N" =>"N", + "O" =>"O", + "P" =>"P", + "Q" =>"Q", + "R" =>"R", + "S" =>"S", + "T" =>"T", + "U" =>"U", + "V" =>"V", + "W" =>"W", + "X" =>"X", + "Y" =>"Y", + "Z" =>"Z", + "[" =>"[", + "\\" =>"\", + "]" =>"]", + "^" =>"^", + "_" =>"_", + "`" =>"`", + "a" =>"a", + "b" =>"b", + "c" =>"c", + "d" =>"d", + "e" =>"e", + "f" =>"f", + "g" =>"g", + "h" =>"h", + "i" =>"i", + "j" =>"j", + "k" =>"k", + "l" =>"l", + "m" =>"m", + "n" =>"n", + "o" =>"o", + "p" =>"p", + "q" =>"q", + "r" =>"r", + "s" =>"s", + "t" =>"t", + "u" =>"u", + "v" =>"v", + "w" =>"w", + "x" =>"x", + "y" =>"y", + "z" =>"z", + "{" =>"{", + "|" =>"|", + "}" =>"}", + "~" =>"~", + " " =>"\u{3000}", + "0" =>"0", + "1" =>"1", + "2" =>"2", + "3" =>"3", + "4" =>"4", + "5" =>"5", + "6" =>"6", + "7" =>"7", + "8" =>"8", + "9" =>"9", + "ァ" =>"ァ", + "ア" =>"ア", + "ィ" =>"ィ", + "イ" =>"イ", + "ゥ" =>"ゥ", + "ウ" =>"ウ", + "ェ" =>"ェ", + "エ" =>"エ", + "ォ" =>"ォ", + "オ" =>"オ", + "カ" =>"カ", + "ガ" =>"ガ", + "キ" =>"キ", + "ギ" =>"ギ", + "ク" =>"ク", + "グ" =>"グ", + "ケ" =>"ケ", + "ゲ" =>"ゲ", + "コ" =>"コ", + "ゴ" =>"ゴ", + "サ" =>"サ", + "ザ" =>"ザ", + "シ" =>"シ", + "ジ" =>"ジ", + "ス" =>"ス", + "ズ" =>"ズ", + "セ" =>"セ", + "ゼ" =>"ゼ", + "ソ" =>"ソ", + "ゾ" =>"ゾ", + "タ" =>"タ", + "ダ" =>"ダ", + "チ" =>"チ", + "ヂ" =>"ヂ", + "ッ" =>"ッ", + "ツ" =>"ツ", + "ヅ" =>"ヅ", + "テ" =>"テ", + "デ" =>"デ", + "ト" =>"ト", + "ド" =>"ド", + "ナ" =>"ナ", + "ニ" =>"ニ", + "ヌ" =>"ヌ", + "ネ" =>"ネ", + "ノ" =>"ノ", + "ハ" =>"ハ", + "バ" =>"バ", + "パ" =>"パ", + "ヒ" =>"ヒ", + "ビ" =>"ビ", + "ピ" =>"ピ", + "フ" =>"フ", + "ブ" =>"ブ", + "プ" =>"プ", + "ヘ" =>"ヘ", + "ベ" =>"ベ", + "ペ" =>"ペ", + "ホ" =>"ホ", + "ボ" =>"ボ", + "ポ" =>"ポ", + "マ" =>"マ", + "ミ" =>"ミ", + "ム" =>"ム", + "メ" =>"メ", + "モ" =>"モ", + "ャ" =>"ャ", + "ヤ" =>"ヤ", + "ュ" =>"ュ", + "ユ" =>"ユ", + "ョ" =>"ョ", + "ヨ" =>"ヨ", + "ラ" =>"ラ", + "リ" =>"リ", + "ル" =>"ル", + "レ" =>"レ", + "ロ" =>"ロ", + "ワ" =>"ワ", + "ヲ" =>"ヲ", + "ン" =>"ン", + "ー" =>"ー", + "ヮ" =>"ヮ", + "ヰ" =>"ヰ", + "ヱ" =>"ヱ", + "ヵ" =>"ヵ", + "ヶ" =>"ヶ", + "ヴ" =>"ヴ", + "ヽ" =>"ヽ", + "ヾ" =>"ヾ", + "・" =>"・", + "「" =>"「", + "」" =>"」", + "。" =>"。", + "、" =>"、" +}; +pub static MAPPINGS_RU: phf::Map<&'static str, &'static str> = phf_map!{ + "а" =>"a", + "б" =>"b", + "в" =>"v", + "г" =>"g", + "д" =>"d", + "е" =>"e", + "ё" =>"e", + "ж" =>"zh", + "з" =>"z", + "и" =>"i", + "й" =>"i", + "к" =>"k", + "л" =>"l", + "м" =>"m", + "н" =>"n", + "о" =>"o", + "п" =>"p", + "р" =>"r", + "с" =>"s", + "т" =>"t", + "у" =>"u", + "ф" =>"f", + "х" =>"kh", + "ц" =>"tc", + "ч" =>"ch", + "ш" =>"sh", + "щ" =>"shch", + "ъ" =>"", + "ы" =>"y", + "ь" =>"'", + "э" =>"e", + "ю" =>"iu", + "я" =>"ia", + "А" =>"A", + "Б" =>"B", + "В" =>"V", + "Г" =>"G", + "Д" =>"D", + "Е" =>"E", + "Ё" =>"E", + "Ж" =>"Zh", + "З" =>"Z", + "И" =>"I", + "Й" =>"I", + "К" =>"K", + "Л" =>"L", + "М" =>"M", + "Н" =>"N", + "О" =>"O", + "П" =>"P", + "Р" =>"R", + "С" =>"S", + "Т" =>"T", + "У" =>"U", + "Ф" =>"F", + "Х" =>"Kh", + "Ц" =>"Tc", + "Ч" =>"Ch", + "Ш" =>"Sh", + "Щ" =>"Shch", + "Ъ" =>"", + "Ы" =>"Y", + "Ь" =>"'", + "Э" =>"E", + "Ю" =>"Iu", + "Я" =>"Ia" +}; +pub static MAPPINGS_DE: phf::Map<&'static str, &'static str> = phf_map!{ + "Ä" => "Ae", + "ä" => "ae", + "Ö" => "Oe", + "ö" => "oe", + "Ü" => "Ue", + "ü" => "ue", + "ß" => "ss" +}; +pub static MAPPINGS_HW: phf::Map<&'static str, &'static str> = phf_map!{ + "-" =>"-", + "ー" =>"-", + "ァ" =>"ァ", + "ア" =>"ア", + "ィ" =>"ィ", + "イ" =>"イ", + "ゥ" =>"ゥ", + "ウ" =>"ウ", + "ェ" =>"ェ", + "エ" =>"エ", + "ォ" =>"ォ", + "オ" =>"オ", + "カ" =>"カ", + "ガ" =>"ガ", + "キ" =>"キ", + "ギ" =>"ギ", + "ク" =>"ク", + "グ" =>"グ", + "ケ" =>"ケ", + "ゲ" =>"ゲ", + "コ" =>"コ", + "ゴ" =>"ゴ", + "サ" =>"サ", + "ザ" =>"ザ", + "シ" =>"シ", + "ジ" =>"ジ", + "ス" =>"ス", + "ズ" =>"ズ", + "セ" =>"セ", + "ゼ" =>"ゼ", + "ソ" =>"ソ", + "ゾ" =>"ゾ", + "タ" =>"タ", + "ダ" =>"ダ", + "チ" =>"チ", + "ヂ" =>"ヂ", + "ッ" =>"ッ", + "ツ" =>"ツ", + "ヅ" =>"ヅ", + "テ" =>"テ", + "デ" =>"デ", + "ト" =>"ト", + "ド" =>"ド", + "ナ" =>"ナ", + "ニ" =>"ニ", + "ヌ" =>"ヌ", + "ネ" =>"ネ", + "ノ" =>"ノ", + "ハ" =>"ハ", + "バ" =>"バ", + "パ" =>"パ", + "ヒ" =>"ヒ", + "ビ" =>"ビ", + "ピ" =>"ピ", + "フ" =>"フ", + "ブ" =>"ブ", + "プ" =>"プ", + "ヘ" =>"ヘ", + "ベ" =>"ベ", + "ペ" =>"ペ", + "ホ" =>"ホ", + "ボ" =>"ボ", + "ポ" =>"ポ", + "マ" =>"マ", + "ミ" =>"ミ", + "ム" =>"ム", + "メ" =>"メ", + "モ" =>"モ", + "ャ" =>"ャ", + "ヤ" =>"ヤ", + "ュ" =>"ュ", + "ユ" =>"ユ", + "ョ" =>"ョ", + "ヨ" =>"ヨ", + "ラ" =>"ラ", + "リ" =>"リ", + "ル" =>"ル", + "レ" =>"レ", + "ロ" =>"ロ", + "ワ" =>"ワ", + "ヲ" =>"ヲ", + "ン" =>"ン", + "ー" =>"-", + "ヮ" =>"ヮ", + "ヰ" =>"ヰ", + "ヱ" =>"ヱ", + "ヵ" =>"ヵ", + "ヶ" =>"ヶ", + "ヴ" =>"ヴ", + "ヽ" =>"ヽ", + "ヾ" =>"ヾ", + "・" =>"・", + "「" =>"「", + "」" =>"」", + "。" =>"。", + "、" =>"、", + "!" =>"!", + """ =>"\"", + "#" =>"#", + "$" =>"$", + "%" =>"%", + "&" =>"&", + "'" =>"'", + "(" =>"", + ")" =>")", + "*" =>"*", + "+" =>"+", + "," =>",", + "." =>".", + "/" =>"/", + ":" =>":", + ";" =>";", + "<" =>"<", + "=" =>"=", + ">" =>">", + "?" =>"?", + "@" =>"@", + "A" =>"A", + "B" =>"B", + "C" =>"C", + "D" =>"D", + "E" =>"E", + "F" =>"F", + "G" =>"G", + "H" =>"H", + "I" =>"I", + "J" =>"J", + "K" =>"K", + "L" =>"L", + "M" =>"M", + "N" =>"N", + "O" =>"O", + "P" =>"P", + "Q" =>"Q", + "R" =>"R", + "S" =>"S", + "T" =>"T", + "U" =>"U", + "V" =>"V", + "W" =>"W", + "X" =>"X", + "Y" =>"Y", + "Z" =>"Z", + "[" =>"[", + "\" =>"\\", + "]" =>"]", + "^" =>"^", + "_" =>"_", + "`" =>"`", + "a" =>"a", + "b" =>"b", + "c" =>"c", + "d" =>"d", + "e" =>"e", + "f" =>"f", + "g" =>"g", + "h" =>"h", + "i" =>"i", + "j" =>"j", + "k" =>"k", + "l" =>"l", + "m" =>"m", + "n" =>"n", + "o" =>"o", + "p" =>"p", + "q" =>"q", + "r" =>"r", + "s" =>"s", + "t" =>"t", + "u" =>"u", + "v" =>"v", + "w" =>"w", + "x" =>"x", + "y" =>"y", + "z" =>"z", + "{" =>"{", + "|" =>"|", + "}" =>"}", + "~" =>"~", + " " =>" ", + "0" =>"0", + "1" =>"1", + "2" =>"2", + "3" =>"3", + "4" =>"4", + "5" =>"5", + "6" =>"6", + "7" =>"7", + "8" =>"8", + "9" =>"9", + "ぁ" =>"ァ", + "あ" =>"ア", + "ぃ" =>"ィ", + "い" =>"イ", + "ぅ" =>"ゥ", + "う" =>"ウ", + "ぇ" =>"ェ", + "え" =>"エ", + "ぉ" =>"ォ", + "お" =>"オ", + "か" =>"カ", + "が" =>"ガ", + "き" =>"キ", + "ぎ" =>"ギ", + "く" =>"ク", + "ぐ" =>"グ", + "け" =>"ケ", + "げ" =>"ゲ", + "こ" =>"コ", + "ご" =>"ゴ", + "さ" =>"サ", + "ざ" =>"ザ", + "し" =>"シ", + "じ" =>"ジ", + "す" =>"ス", + "ず" =>"ズ", + "せ" =>"セ", + "ぜ" =>"ゼ", + "そ" =>"ソ", + "ぞ" =>"ゾ", + "た" =>"タ", + "だ" =>"ダ", + "ち" =>"チ", + "ぢ" =>"ヂ", + "っ" =>"ッ", + "つ" =>"ツ", + "づ" =>"ヅ", + "て" =>"テ", + "で" =>"デ", + "と" =>"ト", + "ど" =>"ド", + "な" =>"ナ", + "に" =>"ニ", + "ぬ" =>"ヌ", + "ね" =>"ネ", + "の" =>"ノ", + "は" =>"ハ", + "ば" =>"バ", + "ぱ" =>"パ", + "ひ" =>"ヒ", + "び" =>"ビ", + "ぴ" =>"ピ", + "ふ" =>"フ", + "ぶ" =>"ブ", + "ぷ" =>"プ", + "へ" =>"ヘ", + "べ" =>"ベ", + "ぺ" =>"ペ", + "ほ" =>"ホ", + "ぼ" =>"ボ", + "ぽ" =>"ポ", + "ま" =>"マ", + "み" =>"ミ", + "む" =>"ム", + "め" =>"メ", + "も" =>"モ", + "ゃ" =>"ャ", + "や" =>"ヤ", + "ゅ" =>"ュ", + "ゆ" =>"ユ", + "ょ" =>"ョ", + "よ" =>"ヨ", + "ら" =>"ラ", + "り" =>"リ", + "る" =>"ル", + "れ" =>"レ", + "ろ" =>"ロ", + "わ" =>"ワ", + "を" =>"ヲ", + "ん" =>"ン", + "ゎ" =>"ヮ", + "ゐ" =>"ヰ", + "ゑ" =>"ヱ", + "ゕ" =>"ヵ", + "ゖ" =>"ヶ", + "ゔ" =>"ヴ", + "ゝ" =>"ヽ", + "ゞ" =>"ヾ", +}; +pub static ALLOWED_HW_KANA: &[&'static str] = &[ + "-", + "-", + "ァ", + "ア", + "ィ", + "イ", + "ゥ", + "ウ", + "ェ", + "エ", + "ォ", + "オ", + "カ", + "ガ", + "キ", + "ギ", + "ク", + "グ", + "ケ", + "ゲ", + "コ", + "ゴ", + "サ", + "ザ", + "シ", + "ジ", + "ス", + "ズ", + "セ", + "ゼ", + "ソ", + "ゾ", + "タ", + "ダ", + "チ", + "ヂ", + "ッ", + "ツ", + "ヅ", + "テ", + "デ", + "ト", + "ド", + "ナ", + "ニ", + "ヌ", + "ネ", + "ノ", + "ハ", + "バ", + "パ", + "ヒ", + "ビ", + "ピ", + "フ", + "ブ", + "プ", + "ヘ", + "ベ", + "ペ", + "ホ", + "ボ", + "ポ", + "マ", + "ミ", + "ム", + "メ", + "モ", + "ャ", + "ヤ", + "ュ", + "ユ", + "ョ", + "ヨ", + "ラ", + "リ", + "ル", + "レ", + "ロ", + "ワ", + "ヲ", + "ン", + "-", + "ヮ", + "ヰ", + "ヱ", + "ヵ", + "ヶ", + "ヴ", + "ヽ", + "ヾ", + "・", + "「", + "」", + "。", + "、", + "!", + "\"", + "#", + "$", + "%", + "&", + "'", + "", + ")", + "*", + "+", + ",", + ".", + "/", + ":", + ";", + "<", + "=", + ">", + "?", + "@", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "[", + "\\", + "]", + "^", + "_", + "`", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "{", + "|", + "}", + "~", + " ", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "ァ", + "ア", + "ィ", + "イ", + "ゥ", + "ウ", + "ェ", + "エ", + "ォ", + "オ", + "カ", + "ガ", + "キ", + "ギ", + "ク", + "グ", + "ケ", + "ゲ", + "コ", + "ゴ", + "サ", + "ザ", + "シ", + "ジ", + "ス", + "ズ", + "セ", + "ゼ", + "ソ", + "ゾ", + "タ", + "ダ", + "チ", + "ヂ", + "ッ", + "ツ", + "ヅ", + "テ", + "デ", + "ト", + "ド", + "ナ", + "ニ", + "ヌ", + "ネ", + "ノ", + "ハ", + "バ", + "パ", + "ヒ", + "ビ", + "ピ", + "フ", + "ブ", + "プ", + "ヘ", + "ベ", + "ペ", + "ホ", + "ボ", + "ポ", + "マ", + "ミ", + "ム", + "メ", + "モ", + "ャ", + "ヤ", + "ュ", + "ユ", + "ョ", + "ヨ", + "ラ", + "リ", + "ル", + "レ", + "ロ", + "ワ", + "ヲ", + "ン", + "ヮ", + "ヰ", + "ヱ", + "ヵ", + "ヶ", + "ヴ", + "ヽ", + "ヾ", +]; diff --git a/src/netmd/query_utils.rs b/src/netmd/query_utils.rs index e8bd10d..9be698e 100644 --- a/src/netmd/query_utils.rs +++ b/src/netmd/query_utils.rs @@ -1,23 +1,19 @@ use crate::netmd::utils; -use lazy_static::lazy_static; -use std::collections::hash_map::HashMap; use thiserror::Error; -lazy_static! { - /// %b, w, d, q - explained above (can have endiannes overriden by '>' and '<' operators, f. ex. %>d % = HashMap::from([ - ('b', 1), // byte - ('w', 2), // word - ('d', 4), // doubleword - ('q', 8), // quadword - ]); -} +/// %b, w, d, q - explained above (can have endiannes overriden by '>' and '<' operators, f. ex. %>d % = phf::phf_map!{ + 'b' => 1, // byte + 'w' => 2, // word + 'd' => 4, // doubleword + 'q' => 8, // quadword +}; const DEBUG: bool = false; @@ -37,11 +33,11 @@ pub enum ValueError { } impl QueryValue { - pub fn from_array(value: [u8; S]) -> Self { + pub fn _from_array(value: [u8; S]) -> Self { Self::Array(value.to_vec()) } - pub fn to_array(&self) -> Result<[u8; S], ValueError> { + pub fn _to_array(&self) -> Result<[u8; S], ValueError> { let mut array = [0u8; S]; match self { QueryValue::Array(a) => { @@ -78,6 +74,20 @@ impl QueryValue { } } +impl TryInto for QueryValue { + type Error = ValueError; + + fn try_into(self) -> Result { + match self { + QueryValue::Number(a) => Ok(a), + _ => Err(ValueError::TypeMismatch { + expected: String::from("i64"), + actual: format!("{:?}", self) + }), + } + } +} + #[derive(Error, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum QueryError { #[error("unrecognized format character: `{0}`")] diff --git a/src/netmd/utils.rs b/src/netmd/utils.rs index 319bdc0..55d86a7 100644 --- a/src/netmd/utils.rs +++ b/src/netmd/utils.rs @@ -8,7 +8,7 @@ use unicode_normalization::UnicodeNormalization; extern crate kana; use kana::*; -/// Sleep for a specified number of milliseconds on any platform +/// Sleep for a specified [Duration] on any platform pub async fn cross_sleep(duration: Duration) { #[cfg(not(target_family = "wasm"))] std::thread::sleep(duration); @@ -75,29 +75,34 @@ pub fn get_bytes(iterator: &mut IntoIter) -> Result<[u8; S], Ok(bytes) } -pub fn length_after_encoding_to_jis(string: &str) -> usize { +pub fn length_after_encoding_to_sjis(string: &str) -> usize { let new_string = SHIFT_JIS.encode(string); new_string.0.len() } -pub fn validate_shift_jis(sjis_string: Vec) -> bool { +pub fn validate_sjis(sjis_string: Vec) -> bool { let (_, _, had_errors) = SHIFT_JIS.decode(&sjis_string); had_errors } +/// Ensure string contains only hardware allowed characters fn check(string: String) -> Option { - if MAPPINGS_HW.contains_key(&string) { - return Some(MAPPINGS_HW.get(&string).unwrap().to_string()); + if MAPPINGS_HW.contains_key(string.as_str()) { + return Some(MAPPINGS_HW.get(string.as_str()).unwrap().to_string()); } let mut ch = string.chars(); - if (ch.next().unwrap() as u32) < 0x7f || ALLOWED_HW_KANA.contains(&string) { + if (ch.next().unwrap() as u32) < 0x7f || ALLOWED_HW_KANA.contains(&string.as_str()) { return Some(string); } None } +fn half_width_title_length(title: &str) { + +} + pub fn sanitize_half_width_title(title: &str) -> Vec { let mut string_title = wide2ascii(title); string_title = nowidespace(&string_title); @@ -115,7 +120,7 @@ pub fn sanitize_half_width_title(title: &str) -> Vec { let sjis_string = SHIFT_JIS.encode(&new_title).0; - if validate_shift_jis(sjis_string.clone().into()) { + if validate_sjis(sjis_string.clone().into()) { return agressive_sanitize_title(title).into(); } @@ -126,24 +131,25 @@ pub fn sanitize_half_width_title(title: &str) -> Vec { pub fn sanitize_full_width_title(title: &str, just_remap: bool) -> Vec { let new_title: String = title .chars() + .map(|c| c.to_string()) .map(|character| { - match MAPPINGS_JP.get(&character.to_string()) { - Some(string) => string.clone(), - None => character.to_string().clone(), + match MAPPINGS_JP.get(character.to_string().as_str()) { + Some(string) => string, + None => character.as_str(), } .to_string() }) .map(|character| { - match MAPPINGS_RU.get(&character.to_string()) { - Some(string) => string.clone(), - None => character.to_string().clone(), + match MAPPINGS_RU.get(character.as_str()) { + Some(string) => string, + None => character.as_str(), } .to_string() }) .map(|character| { - match MAPPINGS_DE.get(&character.to_string()) { - Some(string) => string.clone(), - None => character.to_string().clone(), + match MAPPINGS_DE.get(character.as_str()) { + Some(string) => string, + None => character.as_str(), } .to_string() }) @@ -155,7 +161,7 @@ pub fn sanitize_full_width_title(title: &str, just_remap: bool) -> Vec { let sjis_string = SHIFT_JIS.encode(&new_title).0; - if validate_shift_jis(sjis_string.clone().into()) { + if validate_sjis(sjis_string.clone().into()) { return agressive_sanitize_title(title).into(); } @@ -173,9 +179,28 @@ pub fn agressive_sanitize_title(title: &str) -> String { .into() } -pub fn time_to_duration(time: &[u64]) -> std::time::Duration { - assert_eq!(time.len(), 4); - std::time::Duration::from_micros( - (time[0] * 3600000000) + (time[1] * 60000000) + (time[2] * 1000000) + (time[3] * 11600), - ) +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct RawTime { + pub hours: u64, + pub minutes: u64, + pub seconds: u64, + pub frames: u64, +} + +impl Into for RawTime { + fn into(self) -> std::time::Duration { + self.as_duration() + } +} + +impl RawTime { + pub fn as_duration(&self) -> Duration { + std::time::Duration::from_micros( + (self.hours * 3600000000) + (self.minutes * 60000000) + (self.seconds * 1000000) + (self.frames * 11600), + ) + } + + pub fn as_frames(&self) -> u64 { + ((self.hours * 60 + self.minutes) * 60 + self.seconds) * 512 + self.frames + } }