bms_utils/bms/
token.rs

1#[derive(Clone, Debug, PartialEq)]
2pub(crate) enum Token {
3    Command(Command),
4    ControlFlow(ControlFlow),
5    Comment,
6}
7impl winnow::stream::ContainsToken<Token> for Token {
8    #[inline(always)]
9    fn contains_token(&self, token: Token) -> bool {
10        *self == token
11    }
12}
13impl winnow::stream::ContainsToken<Token> for &[Token] {
14    #[inline]
15    fn contains_token(&self, token: Token) -> bool {
16        self.iter().any(|t| *t == token)
17    }
18}
19
20#[derive(Clone, Debug, PartialEq)]
21pub(crate) enum Command {
22    MainData(usize, MainDataValue),
23    Player(i32),
24    Rank(i32),
25    DefExRank(f64),
26    ExRank(Channel, f64),
27    Total(f64),
28    VolumeWav(f64),
29    StageFile(String),
30    Banner(String),
31    BackBmp(String),
32    CharacterFile(String),
33    PlayLevel(i32),
34    Difficulty(i32),
35    Title(String),
36    SubTitle(String),
37    Artist(String),
38    SubArtist(String),
39    Maker(String),
40    Genre(String),
41    Comment(String),
42    Text(Channel, String),
43    PathWav(String),
44    Bpm(f64),
45    ExBpm(Channel, f64),
46    BaseBpm(f64),
47    Stop(Channel, f64),
48    Stp(usize, u32, f64),
49    LnMode(i32),
50    LnType(i32),
51    LnObject(Channel),
52    OctFp,
53    Option(String, String),
54    ChangeOption(Channel, String, String),
55    Wav(Channel, String),
56    WavCommand(i32, Channel, f64),
57    ExWav(Channel, [Option<f64>; 3], String),
58    Cdda(u32),
59    MidiFile(String),
60    Bmp(Channel, String),
61    ExBmp(Channel, [u8; 4], String),
62    Bga(Channel, Channel, [[f64; 2]; 3]),
63    AtBga(Channel, Channel, [[f64; 2]; 3]),
64    PoorBga(i32),
65    SwitchBga(Channel, f64, f64, Channel, bool, [u8; 4], Vec<Channel>),
66    Argb(Channel, [u8; 4]),
67    VideoFile(String),
68    VideoFps(f64),
69    VideoColors(u32),
70    VideoDelay(u32),
71    Movie(String),
72    Seek(Channel, f64),
73    ExCharacter(
74        u32,
75        usize,
76        [[f64; 2]; 2],
77        Option<[f64; 2]>,
78        Option<[f64; 2]>,
79    ),
80    Url(String),
81    Email(String),
82    Scroll(Channel, f64),
83    Speed(Channel, f64),
84    Preview(String),
85    /// 旧型BPM変更( 16進数 )と地雷( 36進数 )以外の
86    /// WAV BMP BPM STOP SCROLLのチャンネルの指定と参照を62進数で解釈する
87    Base62,
88    /// その他のコマンド
89    Other(String, String),
90}
91#[derive(Clone, Debug, PartialEq)]
92pub(crate) enum MainDataValue {
93    Bgm(Vec<Channel>),
94    Length(f64),
95    Bga(Vec<Channel>),
96    Bpm(Vec<Option<f64>>),
97    BgaPoor(Vec<Channel>),
98    BgaLayer(Vec<Channel>),
99    ExBpm(Vec<Channel>),
100    Stop(Vec<Channel>),
101    BgaLayer2(Vec<Channel>),
102    ExRank(Vec<Channel>),
103    BgaAlpha(Vec<u8>),
104    BgaLayerAlpha(Vec<u8>),
105    BgaLayer2Alpha(Vec<u8>),
106    BgaPoorAlpha(Vec<u8>),
107    Note(usize, Vec<Channel>),
108    InvisibleNote(usize, Vec<Channel>),
109    LongNote(usize, Vec<Channel>),
110    Text(Vec<Channel>),
111    BgaArgb(Vec<Channel>),
112    BgaLayerArgb(Vec<Channel>),
113    BgaLayer2Argb(Vec<Channel>),
114    BgaPoorArgb(Vec<Channel>),
115    SwitchBga(Vec<Channel>),
116    Option(Vec<Channel>),
117    Landmine(usize, Vec<f64>),
118    Scroll(Vec<Channel>),
119    Speed(Vec<Channel>),
120    Other(usize, String),
121}
122#[derive(Clone, Debug, PartialEq)]
123pub(crate) enum ControlFlow {
124    Random(u128),
125    SetRandom(u128),
126    EndRandom,
127    If(u128),
128    ElseIf(u128),
129    Else,
130    EndIf,
131    Switch(u128),
132    SetSwitch(u128),
133    EndSwitch,
134    Case(u128),
135    Skip,
136    Default,
137}
138
139/// 整数・アルファベット大文字小文字の二文字分
140///
141/// 36進数か62進数かの確定前の型
142#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
143pub struct Channel([i32; 2]);
144impl From<&str> for Channel {
145    fn from(value: &str) -> Self {
146        Self::new(value)
147    }
148}
149impl Channel {
150    const fn parse_base_62(c: u8) -> i32 {
151        if c.is_ascii_digit() {
152            (c - b'0') as i32
153        }
154        else if c.is_ascii_uppercase() {
155            (c - b'A') as i32 + 10
156        }
157        else if c.is_ascii_lowercase() {
158            (c - b'a') as i32 + 36
159        }
160        else {
161            0
162        }
163    }
164    pub const fn new(s: &str) -> Channel {
165        let s = s.as_bytes();
166        match s.len() {
167            0 => Channel([0, 0]),
168            1 => Channel([0, Self::parse_base_62(s[0])]),
169            2.. => {
170                Channel([Self::parse_base_62(s[0]), Self::parse_base_62(s[1])])
171            }
172        }
173    }
174    pub const fn to_base_36_or_62(&self, flag: bool) -> usize {
175        if flag {
176            self.to_base_62()
177        }
178        else {
179            self.to_base_36()
180        }
181    }
182    const fn convert_base_36(n: i32) -> i32 {
183        if n < 36 { n } else { n - 26 }
184    }
185    pub const fn to_base_36(&self) -> usize {
186        (36 * Self::convert_base_36(self.0[0])
187            + Self::convert_base_36(self.0[1])) as usize
188    }
189    pub const fn to_base_62(&self) -> usize {
190        (62 * self.0[0] + self.0[1]) as usize
191    }
192}
193
194#[cfg(test)]
195mod tests {
196    #[test]
197    fn channel_to_number() {
198        use super::Channel;
199
200        let zero1 = Channel::from("0");
201        let zero2 = Channel::from("00");
202        let one = Channel::from("1");
203        let ua = Channel::from("A");
204        let uz = Channel::from("Z");
205        let la = Channel::from("a");
206        let lz = Channel::from("z");
207        let ten = Channel::from("10");
208        let invalid = Channel::from("テスト");
209
210        assert_eq!(zero1.to_base_36(), 0);
211        assert_eq!(zero1.to_base_62(), 0);
212
213        assert_eq!(zero2.to_base_36(), 0);
214        assert_eq!(zero2.to_base_62(), 0);
215
216        assert_eq!(one.to_base_36(), 1);
217        assert_eq!(one.to_base_62(), 1);
218
219        assert_eq!(ua.to_base_36(), 10);
220        assert_eq!(ua.to_base_62(), 10);
221
222        assert_eq!(uz.to_base_36(), 35);
223        assert_eq!(uz.to_base_62(), 35);
224
225        assert_eq!(la.to_base_36(), 10);
226        assert_eq!(la.to_base_62(), 36);
227
228        assert_eq!(lz.to_base_36(), 35);
229        assert_eq!(lz.to_base_62(), 61);
230
231        assert_eq!(ten.to_base_36(), 36);
232        assert_eq!(ten.to_base_62(), 62);
233
234        assert_eq!(invalid.to_base_36(), 0);
235        assert_eq!(invalid.to_base_62(), 0);
236    }
237}