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),
54 ChangeOption(Channel, 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 Base62,
88 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#[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}