1use std::path::Path;
6
7use crate::bms::{
8 Decimal,
9 command::{
10 ObjId,
11 channel::Channel,
12 time::{ObjTime, Track},
13 },
14};
15
16use super::{ParseWarning, Result};
17use crate::bms::{
18 model::def::{AtBgaDef, BgaDef, Bmp, ExRankDef},
19 model::obj::{
20 BgaObj, BgmVolumeObj, BpmChangeObj, JudgeObj, KeyVolumeObj, ScrollingFactorObj,
21 SectionLenChangeObj, SpeedObj, TextObj,
22 },
23};
24
25#[cfg(feature = "minor-command")]
26use crate::bms::{
27 command::{
28 graphics::Argb,
29 minor_command::{StpEvent, SwBgaEvent, WavCmdEvent},
30 },
31 model::{
32 def::ExWavDef,
33 obj::{BgaArgbObj, BgaKeyboundObj, BgaOpacityObj, OptionObj, SeekObj},
34 },
35};
36
37pub trait PromptHandler {
39 fn handle_def_duplication(&mut self, duplication: DefDuplication) -> DuplicationWorkaround;
41 fn handle_track_duplication(&mut self, duplication: TrackDuplication) -> DuplicationWorkaround;
43 fn handle_channel_duplication(
45 &mut self,
46 duplication: ChannelDuplication,
47 ) -> DuplicationWorkaround;
48}
49
50#[derive(Debug, Clone, PartialEq)]
52#[non_exhaustive]
53pub enum DefDuplication<'a> {
54 Bmp {
56 id: ObjId,
58 older: &'a Bmp,
60 newer: &'a Bmp,
62 },
63 BpmChange {
65 id: ObjId,
67 older: Decimal,
69 newer: Decimal,
71 },
72 ChangeOption {
74 id: ObjId,
76 older: &'a str,
78 newer: &'a str,
80 },
81 SpeedFactorChange {
83 id: ObjId,
85 older: Decimal,
87 newer: Decimal,
89 },
90 ScrollingFactorChange {
92 id: ObjId,
94 older: Decimal,
96 newer: Decimal,
98 },
99 Text {
101 id: ObjId,
103 older: &'a str,
105 newer: &'a str,
107 },
108 Wav {
110 id: ObjId,
112 older: &'a Path,
114 newer: &'a Path,
116 },
117 AtBga {
119 id: ObjId,
121 older: &'a AtBgaDef,
123 newer: &'a AtBgaDef,
125 },
126 Bga {
128 id: ObjId,
130 older: &'a BgaDef,
132 newer: &'a BgaDef,
134 },
135 ExRank {
137 id: ObjId,
139 older: &'a ExRankDef,
141 newer: &'a ExRankDef,
143 },
144 #[cfg(feature = "minor-command")]
146 ExWav {
147 id: ObjId,
149 older: &'a ExWavDef,
151 newer: &'a ExWavDef,
153 },
154 Stop {
156 id: ObjId,
158 older: Decimal,
160 newer: Decimal,
162 },
163 #[cfg(feature = "minor-command")]
165 BgaArgb {
166 id: ObjId,
168 older: &'a Argb,
170 newer: &'a Argb,
172 },
173 #[cfg(feature = "minor-command")]
175 WavCmdEvent {
176 wav_index: ObjId,
178 older: &'a WavCmdEvent,
180 newer: &'a WavCmdEvent,
182 },
183 #[cfg(feature = "minor-command")]
185 SwBgaEvent {
186 id: ObjId,
188 older: &'a SwBgaEvent,
190 newer: &'a SwBgaEvent,
192 },
193 #[cfg(feature = "minor-command")]
195 SeekEvent {
196 id: ObjId,
198 older: &'a Decimal,
200 newer: &'a Decimal,
202 },
203}
204
205pub enum TrackDuplication<'a> {
207 SectionLenChangeEvent {
209 track: Track,
211 older: &'a SectionLenChangeObj,
213 newer: &'a SectionLenChangeObj,
215 },
216}
217
218pub enum ChannelDuplication<'a> {
220 BpmChangeEvent {
222 time: ObjTime,
224 older: &'a BpmChangeObj,
226 newer: &'a BpmChangeObj,
228 },
229 ScrollingFactorChangeEvent {
231 time: ObjTime,
233 older: &'a ScrollingFactorObj,
235 newer: &'a ScrollingFactorObj,
237 },
238 SpeedFactorChangeEvent {
240 time: ObjTime,
242 older: &'a SpeedObj,
244 newer: &'a SpeedObj,
246 },
247 BgaChangeEvent {
249 time: ObjTime,
251 older: &'a BgaObj,
253 newer: &'a BgaObj,
255 },
256 #[cfg(feature = "minor-command")]
258 BgaOpacityChangeEvent {
259 time: ObjTime,
261 older: &'a BgaOpacityObj,
263 newer: &'a BgaOpacityObj,
265 },
266 #[cfg(feature = "minor-command")]
268 BgaArgbChangeEvent {
269 time: ObjTime,
271 older: &'a BgaArgbObj,
273 newer: &'a BgaArgbObj,
275 },
276 #[cfg(feature = "minor-command")]
278 StpEvent {
279 time: ObjTime,
281 older: &'a StpEvent,
283 newer: &'a StpEvent,
285 },
286 BgmVolumeChangeEvent {
288 time: ObjTime,
290 older: &'a BgmVolumeObj,
292 newer: &'a BgmVolumeObj,
294 },
295 KeyVolumeChangeEvent {
297 time: ObjTime,
299 older: &'a KeyVolumeObj,
301 newer: &'a KeyVolumeObj,
303 },
304 #[cfg(feature = "minor-command")]
306 SeekMessageEvent {
307 time: ObjTime,
309 older: &'a SeekObj,
311 newer: &'a SeekObj,
313 },
314 TextEvent {
316 time: ObjTime,
318 older: &'a TextObj,
320 newer: &'a TextObj,
322 },
323 JudgeEvent {
325 time: ObjTime,
327 older: &'a JudgeObj,
329 newer: &'a JudgeObj,
331 },
332 #[cfg(feature = "minor-command")]
334 BgaKeyboundEvent {
335 time: ObjTime,
337 older: &'a BgaKeyboundObj,
339 newer: &'a BgaKeyboundObj,
341 },
342 #[cfg(feature = "minor-command")]
344 OptionEvent {
345 time: ObjTime,
347 older: &'a OptionObj,
349 newer: &'a OptionObj,
351 },
352}
353
354#[derive(Debug, Clone, PartialEq, Eq, Hash)]
356#[non_exhaustive]
357pub enum DuplicationWorkaround {
358 UseOlder,
360 UseNewer,
362 WarnAndUseOlder,
364 WarnAndUseNewer,
366}
367
368impl DuplicationWorkaround {
369 pub(crate) fn apply_def<T>(self, target: &mut T, newer: T, id: ObjId) -> Result<()> {
370 match self {
371 Self::UseOlder => Ok(()),
372 Self::UseNewer => {
373 *target = newer;
374 Ok(())
375 }
376 Self::WarnAndUseOlder => Err(ParseWarning::DuplicatingDef(id)),
377 Self::WarnAndUseNewer => {
378 *target = newer;
379 Err(ParseWarning::DuplicatingDef(id))
380 }
381 }
382 }
383
384 pub(crate) fn apply_track<T>(
385 self,
386 target: &mut T,
387 newer: T,
388 track: Track,
389 channel: Channel,
390 ) -> Result<()> {
391 match self {
392 Self::UseOlder => Ok(()),
393 Self::UseNewer => {
394 *target = newer;
395 Ok(())
396 }
397 Self::WarnAndUseOlder => Err(ParseWarning::DuplicatingTrackObj(track, channel)),
398 Self::WarnAndUseNewer => {
399 *target = newer;
400 Err(ParseWarning::DuplicatingTrackObj(track, channel))
401 }
402 }
403 }
404
405 pub(crate) fn apply_channel<T>(
406 self,
407 target: &mut T,
408 newer: T,
409 time: ObjTime,
410 channel: Channel,
411 ) -> Result<()> {
412 match self {
413 Self::UseOlder => Ok(()),
414 Self::UseNewer => {
415 *target = newer;
416 Ok(())
417 }
418 Self::WarnAndUseOlder => Err(ParseWarning::DuplicatingChannelObj(time, channel)),
419 Self::WarnAndUseNewer => {
420 *target = newer;
421 Err(ParseWarning::DuplicatingChannelObj(time, channel))
422 }
423 }
424 }
425}
426
427#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
429pub struct AlwaysUseOlder;
430
431impl PromptHandler for AlwaysUseOlder {
432 fn handle_def_duplication(&mut self, _: DefDuplication) -> DuplicationWorkaround {
433 DuplicationWorkaround::UseOlder
434 }
435
436 fn handle_track_duplication(&mut self, _: TrackDuplication) -> DuplicationWorkaround {
437 DuplicationWorkaround::UseOlder
438 }
439
440 fn handle_channel_duplication(&mut self, _: ChannelDuplication) -> DuplicationWorkaround {
441 DuplicationWorkaround::UseOlder
442 }
443}
444
445#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
447pub struct AlwaysUseNewer;
448
449impl PromptHandler for AlwaysUseNewer {
450 fn handle_def_duplication(&mut self, _: DefDuplication) -> DuplicationWorkaround {
451 DuplicationWorkaround::UseNewer
452 }
453
454 fn handle_track_duplication(&mut self, _: TrackDuplication) -> DuplicationWorkaround {
455 DuplicationWorkaround::UseNewer
456 }
457
458 fn handle_channel_duplication(&mut self, _: ChannelDuplication) -> DuplicationWorkaround {
459 DuplicationWorkaround::UseNewer
460 }
461}
462
463#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
465pub struct AlwaysWarnAndUseOlder;
466
467impl PromptHandler for AlwaysWarnAndUseOlder {
468 fn handle_def_duplication(&mut self, _: DefDuplication) -> DuplicationWorkaround {
469 DuplicationWorkaround::WarnAndUseOlder
470 }
471
472 fn handle_track_duplication(&mut self, _: TrackDuplication) -> DuplicationWorkaround {
473 DuplicationWorkaround::WarnAndUseOlder
474 }
475
476 fn handle_channel_duplication(&mut self, _: ChannelDuplication) -> DuplicationWorkaround {
477 DuplicationWorkaround::WarnAndUseOlder
478 }
479}
480
481#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
483pub struct AlwaysWarnAndUseNewer;
484
485impl PromptHandler for AlwaysWarnAndUseNewer {
486 fn handle_def_duplication(&mut self, _: DefDuplication) -> DuplicationWorkaround {
487 DuplicationWorkaround::WarnAndUseNewer
488 }
489
490 fn handle_track_duplication(&mut self, _: TrackDuplication) -> DuplicationWorkaround {
491 DuplicationWorkaround::WarnAndUseNewer
492 }
493
494 fn handle_channel_duplication(&mut self, _: ChannelDuplication) -> DuplicationWorkaround {
495 DuplicationWorkaround::WarnAndUseNewer
496 }
497}