ot_tools_io/
settings.rs

1//! Settings enums. Mostly related to [`crate::SampleSettingsFile`],
2//! [`crate::projects::SlotAttributes`] and [`crate::MarkersFile`] types.
3
4use ot_tools_io_derive::{
5    enum_try_from_i32_to_signed_types, enum_try_from_u32_to_unsigned_types, IntoSigneds,
6    IntoUnsigneds,
7};
8use serde::{Deserialize, Serialize};
9use std::fmt::Display;
10use thiserror::Error;
11
12/// Errors when parsing a value with [`TryFrom`] for some Enum
13#[derive(Debug, Error)]
14pub enum InvalidValueError {
15    /// Error when parsing values with [`TimeStretchMode::try_from`]
16    #[error(
17        "Invalid time stretch value, only '0' (Off), '2' (Normal) and '3' (Beat) are supported values"
18    )]
19    TimeStretchMode,
20
21    /// Error when parsing values with [`LoopMode::try_from`]
22    #[error(
23        "Invalid loop mode value, only '0' (Off), '1' (Normal) and '2' (PingPong) are supported values"
24    )]
25    LoopMode,
26
27    /// Error when parsing values with [`TrigQuantizationMode::try_from`]
28    #[error("Invalid trig quantization value")]
29    TrigQuantizationMode,
30
31    /// Error when parsing values with [`TrigCondition::try_from`]
32    #[error("Invalid trig condition value")]
33    TrigCondition,
34
35    /// Error when parsing values with [`MidiChannel::try_from`]
36    #[error("Invalid MIDI Channel value")]
37    MidiChannel,
38
39    /// Error when parsing values with [`SlotType::try_from`]
40    #[error("Invalid slot type value, only 'FLEX' and 'STATIC' are supported values")]
41    SlotType,
42}
43
44/// Sample Time Stretch options.
45/// See Octatrack Manual section 13.2.4 ATTRIBUTES
46#[derive(
47    PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq, IntoUnsigneds,
48)]
49#[repr(u8)]
50pub enum TimeStretchMode {
51    /// No time-stretching applied.
52    Off = 0,
53
54    /// Regular time-stretching.
55    #[default]
56    Normal = 2,
57
58    /// Drum / Rhythmic specific algorithm
59    Beat = 3,
60}
61
62#[enum_try_from_u32_to_unsigned_types]
63impl TryFrom<u32> for TimeStretchMode {
64    type Error = InvalidValueError;
65    fn try_from(value: u32) -> Result<Self, Self::Error> {
66        match value {
67            0 => Ok(TimeStretchMode::Off),
68            2 => Ok(TimeStretchMode::Normal),
69            3 => Ok(TimeStretchMode::Beat),
70            _ => Err(InvalidValueError::TimeStretchMode),
71        }
72    }
73}
74
75#[cfg(test)]
76mod ot_time_stretch_mode {
77    mod value {
78        use crate::settings::TimeStretchMode;
79
80        #[test]
81        fn test_off_value() {
82            assert_eq!(TimeStretchMode::Off as u8, 0_u8);
83        }
84        #[test]
85        fn test_normal_value() {
86            assert_eq!(TimeStretchMode::Normal as u8, 2_u8);
87        }
88        #[test]
89        fn test_beat_value() {
90            assert_eq!(TimeStretchMode::Beat as u8, 3_u8);
91        }
92    }
93
94    mod from_value {
95        use crate::settings::TimeStretchMode;
96
97        #[test]
98        fn test_error() {
99            // not in a sequential range with other values
100            // dunno why they implemented it to skip value of 1, possible bug or easter egg?
101            assert!(TimeStretchMode::try_from(&1_u8).is_err());
102            assert_eq!(TimeStretchMode::try_from(&1_u8).unwrap_err().to_string(),  "Invalid time stretch value, only '0' (Off), '2' (Normal) and '3' (Beat) are supported values");
103            for x in 4..u8::MAX {
104                assert!(TimeStretchMode::try_from(&x).is_err());
105                assert_eq!(TimeStretchMode::try_from(&x).unwrap_err().to_string(),  "Invalid time stretch value, only '0' (Off), '2' (Normal) and '3' (Beat) are supported values");
106            }
107        }
108        #[test]
109        fn test_off_from_value() {
110            assert_eq!(
111                TimeStretchMode::Off,
112                TimeStretchMode::try_from(&0_u8).unwrap()
113            );
114        }
115        #[test]
116        fn test_normal_from_value() {
117            assert_eq!(
118                TimeStretchMode::Normal,
119                TimeStretchMode::try_from(&2_u8).unwrap()
120            );
121        }
122        #[test]
123        fn test_beat_from_value() {
124            assert_eq!(
125                TimeStretchMode::Beat,
126                TimeStretchMode::try_from(&3_u8).unwrap()
127            );
128        }
129    }
130}
131
132/// Sample attributes Loop mode options.
133/// See Octatrack Manual section 13.2.4 ATTRIBUTES
134#[derive(
135    PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq, IntoUnsigneds,
136)]
137#[repr(u8)]
138pub enum LoopMode {
139    /// Loop points are ignored and sample will never loop.
140    #[default]
141    Off = 0,
142
143    /// Loop by starting again at the loop start position once playback of the sample reaches loop end.
144    Normal = 1,
145
146    /// Loop by continuously reversing once playback of the sample reaches loop end/loop start.
147    PingPong = 2,
148}
149
150#[enum_try_from_u32_to_unsigned_types]
151impl TryFrom<u32> for LoopMode {
152    type Error = InvalidValueError;
153    fn try_from(value: u32) -> Result<Self, Self::Error> {
154        match value {
155            0 => Ok(LoopMode::Off),
156            1 => Ok(LoopMode::Normal),
157            2 => Ok(LoopMode::PingPong),
158            _ => Err(InvalidValueError::LoopMode),
159        }
160    }
161}
162
163#[cfg(test)]
164mod ot_loop_mode {
165
166    mod value {
167        use crate::settings::LoopMode;
168
169        #[test]
170        fn test_off_value() {
171            assert_eq!(LoopMode::Off as u8, 0_u8);
172        }
173        #[test]
174        fn test_normal_value() {
175            assert_eq!(LoopMode::Normal as u8, 1_u8);
176        }
177        #[test]
178        fn test_beat_value() {
179            assert_eq!(LoopMode::PingPong as u8, 2_u8);
180        }
181    }
182
183    mod from_value {
184        use crate::settings::LoopMode;
185
186        #[test]
187        fn test_error() {
188            for x in 3..u8::MAX {
189                assert!(LoopMode::try_from(&x).is_err());
190                assert_eq!(LoopMode::try_from(&x).unwrap_err().to_string(), "Invalid loop mode value, only '0' (Off), '1' (Normal) and '2' (PingPong) are supported values");
191            }
192        }
193        #[test]
194        fn test_off_from_value() {
195            assert_eq!(LoopMode::Off, LoopMode::try_from(&0_u8).unwrap());
196        }
197        #[test]
198        fn test_normal_from_value() {
199            assert_eq!(LoopMode::Normal, LoopMode::try_from(&1_u8).unwrap());
200        }
201        #[test]
202        fn test_beat_from_value() {
203            assert_eq!(LoopMode::PingPong, LoopMode::try_from(&2_u8).unwrap());
204        }
205    }
206}
207
208/// Sample attributes Trig Quantization options
209/// (quantization when manually triggering samples via track buttons).
210/// See Octatrack Manual section 13.2.4 ATTRIBUTES
211#[derive(
212    PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq, IntoUnsigneds,
213)]
214#[repr(u8)]
215pub enum TrigQuantizationMode {
216    /// Play back immediately, no quantization.
217    #[default]
218    Direct = 255,
219
220    /// Play once the pattern ends
221    PatternLength = 0,
222
223    /// Play after 1 sequencer step(s).
224    OneStep = 1,
225
226    /// Play after 2 sequencer step(s).
227    TwoSteps = 2,
228
229    /// Play after 3 sequencer step(s).
230    ThreeSteps = 3,
231
232    /// Play after 4 sequencer step(s).
233    FourSteps = 4,
234
235    /// Play after 6 sequencer step(s).
236    SixSteps = 5,
237
238    /// Play after 8 sequencer step(s).
239    EightSteps = 6,
240
241    /// Play after 12 sequencer step(s).
242    TwelveSteps = 7,
243
244    /// Play after 16 sequencer step(s).
245    SixteenSteps = 8,
246
247    /// Play after 24 sequencer step(s).
248    TwentyFourSteps = 9,
249
250    /// Play after 32 sequencer step(s).
251    ThirtyTwoSteps = 10,
252
253    /// Play after 48 sequencer step(s).
254    FortyEightSteps = 11,
255
256    /// Play after 64 sequencer step(s).
257    SixtyFourSteps = 12,
258
259    /// Play after 96 sequencer step(s).
260    NinetySixSteps = 13,
261
262    /// Play after 128 sequencer step(s).
263    OneTwentyEightSteps = 14,
264
265    /// Play after 192 sequencer step(s).
266    OneNinetyTwoSteps = 15,
267
268    /// Play after 256 sequencer step(s).
269    TwoFiveSixSteps = 16,
270}
271
272#[enum_try_from_u32_to_unsigned_types]
273impl TryFrom<u32> for TrigQuantizationMode {
274    type Error = InvalidValueError;
275    fn try_from(value: u32) -> Result<Self, Self::Error> {
276        match value {
277            255 => Ok(TrigQuantizationMode::Direct),
278            0 => Ok(TrigQuantizationMode::PatternLength),
279            1 => Ok(TrigQuantizationMode::OneStep),
280            2 => Ok(TrigQuantizationMode::TwoSteps),
281            3 => Ok(TrigQuantizationMode::ThreeSteps),
282            4 => Ok(TrigQuantizationMode::FourSteps),
283            5 => Ok(TrigQuantizationMode::SixSteps),
284            6 => Ok(TrigQuantizationMode::EightSteps),
285            7 => Ok(TrigQuantizationMode::TwelveSteps),
286            8 => Ok(TrigQuantizationMode::SixteenSteps),
287            9 => Ok(TrigQuantizationMode::TwentyFourSteps),
288            10 => Ok(TrigQuantizationMode::ThirtyTwoSteps),
289            11 => Ok(TrigQuantizationMode::FortyEightSteps),
290            12 => Ok(TrigQuantizationMode::SixtyFourSteps),
291            13 => Ok(TrigQuantizationMode::NinetySixSteps),
292            14 => Ok(TrigQuantizationMode::OneTwentyEightSteps),
293            15 => Ok(TrigQuantizationMode::OneNinetyTwoSteps),
294            16 => Ok(TrigQuantizationMode::TwoFiveSixSteps),
295            _ => Err(InvalidValueError::TrigQuantizationMode),
296        }
297    }
298}
299
300#[cfg(test)]
301mod ot_trig_quantize_mode {
302
303    mod value {
304        use crate::settings::TrigQuantizationMode;
305
306        #[test]
307        fn test_direct() {
308            assert_eq!(TrigQuantizationMode::Direct as u8, 255);
309        }
310        #[test]
311        fn test_patternlen() {
312            assert_eq!(TrigQuantizationMode::PatternLength as u8, 0);
313        }
314        #[test]
315        fn test_1() {
316            assert_eq!(TrigQuantizationMode::OneStep as u8, 1);
317        }
318        #[test]
319        fn test_2() {
320            assert_eq!(TrigQuantizationMode::TwoSteps as u8, 2);
321        }
322        #[test]
323        fn test_3() {
324            assert_eq!(TrigQuantizationMode::ThreeSteps as u8, 3);
325        }
326        #[test]
327        fn test_4() {
328            assert_eq!(TrigQuantizationMode::FourSteps as u8, 4);
329        }
330        #[test]
331        fn test_6() {
332            assert_eq!(TrigQuantizationMode::SixSteps as u8, 5);
333        }
334        #[test]
335        fn test_8() {
336            assert_eq!(TrigQuantizationMode::EightSteps as u8, 6);
337        }
338        #[test]
339        fn test_12() {
340            assert_eq!(TrigQuantizationMode::TwelveSteps as u8, 7);
341        }
342        #[test]
343        fn test_16() {
344            assert_eq!(TrigQuantizationMode::SixteenSteps as u8, 8);
345        }
346        #[test]
347        fn test_24() {
348            assert_eq!(TrigQuantizationMode::TwentyFourSteps as u8, 9);
349        }
350        #[test]
351        fn test_32() {
352            assert_eq!(TrigQuantizationMode::ThirtyTwoSteps as u8, 10);
353        }
354        #[test]
355        fn test_48() {
356            assert_eq!(TrigQuantizationMode::FortyEightSteps as u8, 11);
357        }
358        #[test]
359        fn test_64() {
360            assert_eq!(TrigQuantizationMode::SixtyFourSteps as u8, 12);
361        }
362        #[test]
363        fn test_96() {
364            assert_eq!(TrigQuantizationMode::NinetySixSteps as u8, 13);
365        }
366        #[test]
367        fn test_128() {
368            assert_eq!(TrigQuantizationMode::OneTwentyEightSteps as u8, 14);
369        }
370        #[test]
371        fn test_192() {
372            assert_eq!(TrigQuantizationMode::OneNinetyTwoSteps as u8, 15);
373        }
374        #[test]
375        fn test_256() {
376            assert_eq!(TrigQuantizationMode::TwoFiveSixSteps as u8, 16);
377        }
378    }
379
380    mod from_value {
381        use crate::settings::TrigQuantizationMode;
382
383        #[test]
384        fn test_error() {
385            for i in 17..=254_u8 {
386                assert!(TrigQuantizationMode::try_from(i).is_err());
387                assert_eq!(
388                    TrigQuantizationMode::try_from(i).unwrap_err().to_string(),
389                    "Invalid trig quantization value"
390                );
391            }
392        }
393        #[test]
394        fn test_direct() {
395            assert_eq!(
396                TrigQuantizationMode::Direct,
397                TrigQuantizationMode::try_from(255_u8).unwrap()
398            );
399        }
400        #[test]
401        fn test_patternlen() {
402            assert_eq!(
403                TrigQuantizationMode::PatternLength,
404                TrigQuantizationMode::try_from(0_u8).unwrap()
405            );
406        }
407        #[test]
408        fn test_1() {
409            assert_eq!(
410                TrigQuantizationMode::OneStep,
411                TrigQuantizationMode::try_from(1_u8).unwrap()
412            );
413        }
414        #[test]
415        fn test_2() {
416            assert_eq!(
417                TrigQuantizationMode::TwoSteps,
418                TrigQuantizationMode::try_from(2_u8).unwrap()
419            );
420        }
421        #[test]
422        fn test_3() {
423            assert_eq!(
424                TrigQuantizationMode::ThreeSteps,
425                TrigQuantizationMode::try_from(3_u8).unwrap()
426            );
427        }
428        #[test]
429        fn test_4() {
430            assert_eq!(
431                TrigQuantizationMode::FourSteps,
432                TrigQuantizationMode::try_from(4_u8).unwrap()
433            );
434        }
435        #[test]
436        fn test_6() {
437            assert_eq!(
438                TrigQuantizationMode::SixSteps,
439                TrigQuantizationMode::try_from(5_u8).unwrap()
440            );
441        }
442        #[test]
443        fn test_8() {
444            assert_eq!(
445                TrigQuantizationMode::EightSteps,
446                TrigQuantizationMode::try_from(6_u8).unwrap()
447            );
448        }
449        #[test]
450        fn test_12() {
451            assert_eq!(
452                TrigQuantizationMode::TwelveSteps,
453                TrigQuantizationMode::try_from(7_u8).unwrap()
454            );
455        }
456        #[test]
457        fn test_16() {
458            assert_eq!(
459                TrigQuantizationMode::SixteenSteps,
460                TrigQuantizationMode::try_from(8_u8).unwrap()
461            );
462        }
463        #[test]
464        fn test_24() {
465            assert_eq!(
466                TrigQuantizationMode::TwentyFourSteps,
467                TrigQuantizationMode::try_from(9_u8).unwrap()
468            );
469        }
470        #[test]
471        fn test_32() {
472            assert_eq!(
473                TrigQuantizationMode::ThirtyTwoSteps,
474                TrigQuantizationMode::try_from(10_u8).unwrap()
475            );
476        }
477        #[test]
478        fn test_48() {
479            assert_eq!(
480                TrigQuantizationMode::FortyEightSteps,
481                TrigQuantizationMode::try_from(11_u8).unwrap()
482            );
483        }
484        #[test]
485        fn test_64() {
486            assert_eq!(
487                TrigQuantizationMode::SixtyFourSteps,
488                TrigQuantizationMode::try_from(12_u8).unwrap()
489            );
490        }
491        #[test]
492        fn test_96() {
493            assert_eq!(
494                TrigQuantizationMode::NinetySixSteps,
495                TrigQuantizationMode::try_from(13_u8).unwrap()
496            );
497        }
498        #[test]
499        fn test_128() {
500            assert_eq!(
501                TrigQuantizationMode::OneTwentyEightSteps,
502                TrigQuantizationMode::try_from(14_u8).unwrap()
503            );
504        }
505        #[test]
506        fn test_192() {
507            assert_eq!(
508                TrigQuantizationMode::OneNinetyTwoSteps,
509                TrigQuantizationMode::try_from(15_u8).unwrap()
510            );
511        }
512        #[test]
513        fn test_256() {
514            assert_eq!(
515                TrigQuantizationMode::TwoFiveSixSteps,
516                TrigQuantizationMode::try_from(16_u8).unwrap()
517            );
518        }
519    }
520}
521
522/// Sample Slot options for Projects.
523#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq, Hash, IntoUnsigneds)]
524pub enum TrigCondition {
525    // Uses implicit discriminants to increment values from 0 -> 64 (inclusive)
526    // https://doc.rust-lang.org/stable/reference/items/enumerations.html#implicit-discriminants
527    None = 0,
528    /// > FILL is true (will activate the trig) when fill mode is active (see below).
529    Fill,
530    /// > ... true when FILL is not.
531    NotFill,
532    /// > PRE is true if the most recently evaluated trig condition on the same track was true.
533    Pre,
534    /// > ... true when PRE is not.
535    NotPre,
536    /// > true if the most recently evaluated trig condition on the neighbor track was true.
537    /// > The neighbor track is the track before the one being edited.
538    /// > For example, the neighbor track of track 4 is track 3. If no conditions exist on the
539    /// > neighbor track, the condition is false.
540    Nei,
541    /// > ... true when NEI is not.
542    NotNei,
543    /// > only true the first time the pattern play (when looped).
544    First,
545    /// > ... true when 1st is not.
546    NotFirst,
547    /// > probability condition. 1% chance of being true.
548    Percent1,
549    /// > probability condition. 2% chance of being true.
550    Percent2,
551    /// > probability condition. 4% chance of being true.
552    Percent4,
553    /// > probability condition. 6% chance of being true.
554    Percent6,
555    /// > probability condition. 9% chance of being true.
556    Percent9,
557    /// > probability condition. 13% chance of being true.
558    Percent13,
559    /// > probability condition. 19% chance of being true.
560    Percent19,
561    /// > probability condition. 25% chance of being true.
562    Percent25,
563    /// > probability condition. 33% chance of being true.
564    Percent33,
565    /// > probability condition. 41% chance of being true.
566    Percent41,
567    /// > probability condition. 50% chance of being true.
568    Percent50,
569    /// > probability condition. 59% chance of being true.
570    Percent59,
571    /// > probability condition. 67% chance of being true.
572    Percent67,
573    /// > probability condition. 75% chance of being true.
574    Percent75,
575    /// > probability condition. 81% chance of being true.
576    Percent81,
577    /// > probability condition. 87% chance of being true.
578    Percent87,
579    /// > probability condition. 91% chance of being true.
580    Percent91,
581    /// > probability condition. 94% chance of being true.
582    Percent94,
583    /// > probability condition. 96% chance of being true.
584    Percent96,
585    /// > probability condition. 98% chance of being true.
586    Percent98,
587    /// > probability condition. 99% chance of being true.
588    Percent99,
589    /// pattern loop 1 triggers, pattern loop 2 resets
590    PatternT1R2,
591    /// pattern loop 2 triggers, pattern loop 2 resets
592    PatternT2R2,
593    /// pattern loop 1 triggers, pattern loop 3 resets
594    PatternT1R3,
595    /// pattern loop 2 triggers, pattern loop 3 resets
596    PatternT2R3,
597    /// pattern loop 3 triggers, pattern loop 3 resets
598    PatternT3R3,
599    /// pattern loop 1 triggers, pattern loop 4 resets
600    PatternT1R4,
601    /// pattern loop 2 triggers, pattern loop 4 resets
602    PatternT2R4,
603    /// pattern loop 3 triggers, pattern loop 4 resets
604    PatternT3R4,
605    /// pattern loop 4 triggers, pattern loop 4 resets
606    PatternT4R4,
607    /// pattern loop 1 triggers, pattern loop 5 resets
608    PatternT1R5,
609    /// pattern loop 2 triggers, pattern loop 5 resets
610    PatternT2R5,
611    /// pattern loop 3 triggers, pattern loop 5 resets
612    PatternT3R5,
613    /// pattern loop 4 triggers, pattern loop 5 resets
614    PatternT4R5,
615    /// pattern loop 5 triggers, pattern loop 5 resets
616    PatternT5R5,
617    /// pattern loop 1 triggers, pattern loop 6 resets
618    PatternT1R6,
619    /// pattern loop 2 triggers, pattern loop 6 resets
620    PatternT2R6,
621    /// pattern loop 3 triggers, pattern loop 6 resets
622    PatternT3R6,
623    /// pattern loop 4 triggers, pattern loop 6 resets
624    PatternT4R6,
625    /// pattern loop 5 triggers, pattern loop 6 resets
626    PatternT5R6,
627    /// pattern loop 6 triggers, pattern loop 6 resets
628    PatternT6R6,
629    /// pattern loop 1 triggers, pattern loop 7 resets
630    PatternT1R7,
631    /// pattern loop 2 triggers, pattern loop 7 resets
632    PatternT2R7,
633    /// pattern loop 3 triggers, pattern loop 7 resets
634    PatternT3R7,
635    /// pattern loop 4 triggers, pattern loop 7 resets
636    PatternT4R7,
637    /// pattern loop 5 triggers, pattern loop 7 resets
638    PatternT5R7,
639    /// pattern loop 6 triggers, pattern loop 7 resets
640    PatternT6R7,
641    /// pattern loop 7 triggers, pattern loop 7 resets
642    PatternT7R7,
643    /// pattern loop 1 triggers, pattern loop 8 resets
644    PatternT1R8,
645    /// pattern loop 2 triggers, pattern loop 8 resets
646    PatternT2R8,
647    /// pattern loop 3 triggers, pattern loop 8 resets
648    PatternT3R8,
649    /// pattern loop 4 triggers, pattern loop 8 resets
650    PatternT4R8,
651    /// pattern loop 5 triggers, pattern loop 8 resets
652    PatternT5R8,
653    /// pattern loop 6 triggers, pattern loop 8 resets
654    PatternT6R8,
655    /// pattern loop 7 triggers, pattern loop 8 resets
656    PatternT7R8,
657    /// pattern loop 8 triggers, pattern loop 8 resets
658    PatternT8R8,
659}
660
661#[enum_try_from_u32_to_unsigned_types]
662impl TryFrom<u32> for TrigCondition {
663    type Error = InvalidValueError;
664    fn try_from(value: u32) -> Result<Self, Self::Error> {
665        // read the essay for `AudioTrackTrigs.trig_timings_repeats_conditions`
666        // to understand why rem_euclid is used here
667        match value.rem_euclid(128) {
668            0 => Ok(TrigCondition::None),
669            1 => Ok(TrigCondition::Fill),
670            2 => Ok(TrigCondition::NotFill),
671            3 => Ok(TrigCondition::Pre),
672            4 => Ok(TrigCondition::NotPre),
673            5 => Ok(TrigCondition::Nei),
674            6 => Ok(TrigCondition::NotNei),
675            7 => Ok(TrigCondition::First),
676            8 => Ok(TrigCondition::NotFirst),
677            //
678            9 => Ok(TrigCondition::Percent1),
679            10 => Ok(TrigCondition::Percent2),
680            11 => Ok(TrigCondition::Percent4),
681            12 => Ok(TrigCondition::Percent6),
682            13 => Ok(TrigCondition::Percent9),
683            14 => Ok(TrigCondition::Percent13),
684            15 => Ok(TrigCondition::Percent19),
685            16 => Ok(TrigCondition::Percent25),
686            17 => Ok(TrigCondition::Percent33),
687            18 => Ok(TrigCondition::Percent41),
688            19 => Ok(TrigCondition::Percent50),
689            20 => Ok(TrigCondition::Percent59),
690            21 => Ok(TrigCondition::Percent67),
691            22 => Ok(TrigCondition::Percent75),
692            23 => Ok(TrigCondition::Percent81),
693            24 => Ok(TrigCondition::Percent87),
694            25 => Ok(TrigCondition::Percent91),
695            26 => Ok(TrigCondition::Percent94),
696            27 => Ok(TrigCondition::Percent96),
697            28 => Ok(TrigCondition::Percent98),
698            29 => Ok(TrigCondition::Percent99),
699            //
700            30 => Ok(TrigCondition::PatternT1R2),
701            31 => Ok(TrigCondition::PatternT2R2),
702            //
703            32 => Ok(TrigCondition::PatternT1R3),
704            33 => Ok(TrigCondition::PatternT2R3),
705            34 => Ok(TrigCondition::PatternT3R3),
706            //
707            35 => Ok(TrigCondition::PatternT1R4),
708            36 => Ok(TrigCondition::PatternT2R4),
709            37 => Ok(TrigCondition::PatternT3R4),
710            38 => Ok(TrigCondition::PatternT4R4),
711            //
712            39 => Ok(TrigCondition::PatternT1R5),
713            40 => Ok(TrigCondition::PatternT2R5),
714            41 => Ok(TrigCondition::PatternT3R5),
715            42 => Ok(TrigCondition::PatternT4R5),
716            43 => Ok(TrigCondition::PatternT5R5),
717            //
718            44 => Ok(TrigCondition::PatternT1R6),
719            45 => Ok(TrigCondition::PatternT2R6),
720            46 => Ok(TrigCondition::PatternT3R6),
721            47 => Ok(TrigCondition::PatternT4R6),
722            48 => Ok(TrigCondition::PatternT5R6),
723            49 => Ok(TrigCondition::PatternT6R6),
724            //
725            50 => Ok(TrigCondition::PatternT1R7),
726            51 => Ok(TrigCondition::PatternT2R7),
727            52 => Ok(TrigCondition::PatternT3R7),
728            53 => Ok(TrigCondition::PatternT4R7),
729            54 => Ok(TrigCondition::PatternT5R7),
730            55 => Ok(TrigCondition::PatternT6R7),
731            56 => Ok(TrigCondition::PatternT7R7),
732            //
733            57 => Ok(TrigCondition::PatternT1R8),
734            58 => Ok(TrigCondition::PatternT2R8),
735            59 => Ok(TrigCondition::PatternT3R8),
736            60 => Ok(TrigCondition::PatternT4R8),
737            61 => Ok(TrigCondition::PatternT5R8),
738            62 => Ok(TrigCondition::PatternT6R8),
739            63 => Ok(TrigCondition::PatternT7R8),
740            64 => Ok(TrigCondition::PatternT8R8),
741            //
742            _ => Err(InvalidValueError::TrigCondition),
743        }
744    }
745}
746
747#[cfg(test)]
748mod test_spec_trig_condition {
749
750    mod from_value {
751        use crate::settings::TrigCondition;
752
753        #[test]
754        fn none() {
755            assert_eq!(TrigCondition::None, TrigCondition::try_from(&0_u8).unwrap())
756        }
757        #[test]
758        fn fill() {
759            assert_eq!(TrigCondition::Fill, TrigCondition::try_from(&1_u8).unwrap())
760        }
761        #[test]
762        fn notfill() {
763            assert_eq!(
764                TrigCondition::NotFill,
765                TrigCondition::try_from(&2_u8).unwrap()
766            )
767        }
768        #[test]
769        fn pre() {
770            assert_eq!(TrigCondition::Pre, TrigCondition::try_from(&3_u8).unwrap())
771        }
772        #[test]
773        fn notpre() {
774            assert_eq!(
775                TrigCondition::NotPre,
776                TrigCondition::try_from(&4_u8).unwrap()
777            )
778        }
779        #[test]
780        fn nei() {
781            assert_eq!(TrigCondition::Nei, TrigCondition::try_from(&5_u8).unwrap())
782        }
783        #[test]
784        fn notnei() {
785            assert_eq!(
786                TrigCondition::NotNei,
787                TrigCondition::try_from(&6_u8).unwrap()
788            )
789        }
790        #[test]
791        fn first() {
792            assert_eq!(
793                TrigCondition::First,
794                TrigCondition::try_from(&7_u8).unwrap()
795            )
796        }
797        #[test]
798        fn notfirst() {
799            assert_eq!(
800                TrigCondition::NotFirst,
801                TrigCondition::try_from(&8_u8).unwrap()
802            )
803        }
804        #[test]
805        fn perc1() {
806            assert_eq!(
807                TrigCondition::Percent1,
808                TrigCondition::try_from(&9_u8).unwrap()
809            )
810        }
811        #[test]
812        fn perc2() {
813            assert_eq!(
814                TrigCondition::Percent2,
815                TrigCondition::try_from(&10_u8).unwrap()
816            )
817        }
818        #[test]
819        fn perc4() {
820            assert_eq!(
821                TrigCondition::Percent4,
822                TrigCondition::try_from(&11_u8).unwrap()
823            )
824        }
825        #[test]
826        fn perc6() {
827            assert_eq!(
828                TrigCondition::Percent6,
829                TrigCondition::try_from(&12_u8).unwrap()
830            )
831        }
832        #[test]
833        fn perc9() {
834            assert_eq!(
835                TrigCondition::Percent9,
836                TrigCondition::try_from(&13_u8).unwrap()
837            )
838        }
839        #[test]
840        fn perc13() {
841            assert_eq!(
842                TrigCondition::Percent13,
843                TrigCondition::try_from(&14_u8).unwrap()
844            )
845        }
846        #[test]
847        fn perc19() {
848            assert_eq!(
849                TrigCondition::Percent19,
850                TrigCondition::try_from(&15_u8).unwrap()
851            )
852        }
853        #[test]
854        fn perc25() {
855            assert_eq!(
856                TrigCondition::Percent25,
857                TrigCondition::try_from(&16_u8).unwrap()
858            )
859        }
860        #[test]
861        fn perc33() {
862            assert_eq!(
863                TrigCondition::Percent33,
864                TrigCondition::try_from(&17_u8).unwrap()
865            )
866        }
867        #[test]
868        fn perc41() {
869            assert_eq!(
870                TrigCondition::Percent41,
871                TrigCondition::try_from(&18_u8).unwrap()
872            )
873        }
874        #[test]
875        fn perc50() {
876            assert_eq!(
877                TrigCondition::Percent50,
878                TrigCondition::try_from(&19_u8).unwrap()
879            )
880        }
881        #[test]
882        fn perc59() {
883            assert_eq!(
884                TrigCondition::Percent59,
885                TrigCondition::try_from(&20_u8).unwrap()
886            )
887        }
888        #[test]
889        fn perc67() {
890            assert_eq!(
891                TrigCondition::Percent67,
892                TrigCondition::try_from(&21_u8).unwrap()
893            )
894        }
895        #[test]
896        fn perc75() {
897            assert_eq!(
898                TrigCondition::Percent75,
899                TrigCondition::try_from(&22_u8).unwrap()
900            )
901        }
902        #[test]
903        fn perc81() {
904            assert_eq!(
905                TrigCondition::Percent81,
906                TrigCondition::try_from(&23_u8).unwrap()
907            )
908        }
909        #[test]
910        fn perc87() {
911            assert_eq!(
912                TrigCondition::Percent87,
913                TrigCondition::try_from(&24_u8).unwrap()
914            )
915        }
916        #[test]
917        fn perc91() {
918            assert_eq!(
919                TrigCondition::Percent91,
920                TrigCondition::try_from(&25_u8).unwrap()
921            )
922        }
923        #[test]
924        fn perc94() {
925            assert_eq!(
926                TrigCondition::Percent94,
927                TrigCondition::try_from(&26_u8).unwrap()
928            )
929        }
930        #[test]
931        fn perc96() {
932            assert_eq!(
933                TrigCondition::Percent96,
934                TrigCondition::try_from(&27_u8).unwrap()
935            )
936        }
937        #[test]
938        fn perc98() {
939            assert_eq!(
940                TrigCondition::Percent98,
941                TrigCondition::try_from(&28_u8).unwrap()
942            )
943        }
944        #[test]
945        fn perc99() {
946            assert_eq!(
947                TrigCondition::Percent99,
948                TrigCondition::try_from(&29_u8).unwrap()
949            )
950        }
951        #[test]
952        fn pat_t1r2() {
953            assert_eq!(
954                TrigCondition::PatternT1R2,
955                TrigCondition::try_from(&30_u8).unwrap()
956            )
957        }
958        #[test]
959        fn pat_t2r2() {
960            assert_eq!(
961                TrigCondition::PatternT2R2,
962                TrigCondition::try_from(&31_u8).unwrap()
963            )
964        }
965        #[test]
966        fn pat_t1r3() {
967            assert_eq!(
968                TrigCondition::PatternT1R3,
969                TrigCondition::try_from(&32_u8).unwrap()
970            )
971        }
972        #[test]
973        fn pat_t2r3() {
974            assert_eq!(
975                TrigCondition::PatternT2R3,
976                TrigCondition::try_from(&33_u8).unwrap()
977            )
978        }
979        #[test]
980        fn pat_t3r3() {
981            assert_eq!(
982                TrigCondition::PatternT3R3,
983                TrigCondition::try_from(&34_u8).unwrap()
984            )
985        }
986
987        #[test]
988        fn pat_t1r4() {
989            assert_eq!(
990                TrigCondition::PatternT1R4,
991                TrigCondition::try_from(&35_u8).unwrap()
992            )
993        }
994        #[test]
995        fn pat_t2r4() {
996            assert_eq!(
997                TrigCondition::PatternT2R4,
998                TrigCondition::try_from(&36_u8).unwrap()
999            )
1000        }
1001        #[test]
1002        fn pat_t3r4() {
1003            assert_eq!(
1004                TrigCondition::PatternT3R4,
1005                TrigCondition::try_from(&37_u8).unwrap()
1006            )
1007        }
1008        #[test]
1009        fn pat_t4r4() {
1010            assert_eq!(
1011                TrigCondition::PatternT4R4,
1012                TrigCondition::try_from(&38_u8).unwrap()
1013            )
1014        }
1015
1016        #[test]
1017        fn pat_t1r5() {
1018            assert_eq!(
1019                TrigCondition::PatternT1R5,
1020                TrigCondition::try_from(&39_u8).unwrap()
1021            )
1022        }
1023        #[test]
1024        fn pat_t2r5() {
1025            assert_eq!(
1026                TrigCondition::PatternT2R5,
1027                TrigCondition::try_from(&40_u8).unwrap()
1028            )
1029        }
1030        #[test]
1031        fn pat_t3r5() {
1032            assert_eq!(
1033                TrigCondition::PatternT3R5,
1034                TrigCondition::try_from(&41_u8).unwrap()
1035            )
1036        }
1037        #[test]
1038        fn pat_t4r5() {
1039            assert_eq!(
1040                TrigCondition::PatternT4R5,
1041                TrigCondition::try_from(&42_u8).unwrap()
1042            )
1043        }
1044        #[test]
1045        fn pat_t5r5() {
1046            assert_eq!(
1047                TrigCondition::PatternT5R5,
1048                TrigCondition::try_from(&43_u8).unwrap()
1049            )
1050        }
1051
1052        #[test]
1053        fn pat_t1r6() {
1054            assert_eq!(
1055                TrigCondition::PatternT1R6,
1056                TrigCondition::try_from(&44_u8).unwrap()
1057            )
1058        }
1059        #[test]
1060        fn pat_t2r6() {
1061            assert_eq!(
1062                TrigCondition::PatternT2R6,
1063                TrigCondition::try_from(&45_u8).unwrap()
1064            )
1065        }
1066        #[test]
1067        fn pat_t3r6() {
1068            assert_eq!(
1069                TrigCondition::PatternT3R6,
1070                TrigCondition::try_from(&46_u8).unwrap()
1071            )
1072        }
1073        #[test]
1074        fn pat_t4r6() {
1075            assert_eq!(
1076                TrigCondition::PatternT4R6,
1077                TrigCondition::try_from(&47_u8).unwrap()
1078            )
1079        }
1080        #[test]
1081        fn pat_t5r6() {
1082            assert_eq!(
1083                TrigCondition::PatternT5R6,
1084                TrigCondition::try_from(&48_u8).unwrap()
1085            )
1086        }
1087        #[test]
1088        fn pat_t6r6() {
1089            assert_eq!(
1090                TrigCondition::PatternT6R6,
1091                TrigCondition::try_from(&49_u8).unwrap()
1092            )
1093        }
1094
1095        #[test]
1096        fn pat_t1r7() {
1097            assert_eq!(
1098                TrigCondition::PatternT1R7,
1099                TrigCondition::try_from(&50_u8).unwrap()
1100            )
1101        }
1102        #[test]
1103        fn pat_t2r7() {
1104            assert_eq!(
1105                TrigCondition::PatternT2R7,
1106                TrigCondition::try_from(&51_u8).unwrap()
1107            )
1108        }
1109        #[test]
1110        fn pat_t3r7() {
1111            assert_eq!(
1112                TrigCondition::PatternT3R7,
1113                TrigCondition::try_from(&52_u8).unwrap()
1114            )
1115        }
1116        #[test]
1117        fn pat_t4r7() {
1118            assert_eq!(
1119                TrigCondition::PatternT4R7,
1120                TrigCondition::try_from(&53_u8).unwrap()
1121            )
1122        }
1123        #[test]
1124        fn pat_t5r7() {
1125            assert_eq!(
1126                TrigCondition::PatternT5R7,
1127                TrigCondition::try_from(&54_u8).unwrap()
1128            )
1129        }
1130        #[test]
1131        fn pat_t6r7() {
1132            assert_eq!(
1133                TrigCondition::PatternT6R7,
1134                TrigCondition::try_from(&55_u8).unwrap()
1135            )
1136        }
1137        #[test]
1138        fn pat_t7r7() {
1139            assert_eq!(
1140                TrigCondition::PatternT7R7,
1141                TrigCondition::try_from(&56_u8).unwrap()
1142            )
1143        }
1144
1145        #[test]
1146        fn pat_t1r8() {
1147            assert_eq!(
1148                TrigCondition::PatternT1R8,
1149                TrigCondition::try_from(&57_u8).unwrap()
1150            )
1151        }
1152        #[test]
1153        fn pat_t2r8() {
1154            assert_eq!(
1155                TrigCondition::PatternT2R8,
1156                TrigCondition::try_from(&58_u8).unwrap()
1157            )
1158        }
1159        #[test]
1160        fn pat_t3r8() {
1161            assert_eq!(
1162                TrigCondition::PatternT3R8,
1163                TrigCondition::try_from(&59_u8).unwrap()
1164            )
1165        }
1166        #[test]
1167        fn pat_t4r8() {
1168            assert_eq!(
1169                TrigCondition::PatternT4R8,
1170                TrigCondition::try_from(&60_u8).unwrap()
1171            )
1172        }
1173        #[test]
1174        fn pat_t5r8() {
1175            assert_eq!(
1176                TrigCondition::PatternT5R8,
1177                TrigCondition::try_from(&61_u8).unwrap()
1178            )
1179        }
1180        #[test]
1181        fn pat_t6r8() {
1182            assert_eq!(
1183                TrigCondition::PatternT6R8,
1184                TrigCondition::try_from(&62_u8).unwrap()
1185            )
1186        }
1187        #[test]
1188        fn pat_t7r8() {
1189            assert_eq!(
1190                TrigCondition::PatternT7R8,
1191                TrigCondition::try_from(&63_u8).unwrap()
1192            )
1193        }
1194        #[test]
1195        fn pat_t8r8() {
1196            assert_eq!(
1197                TrigCondition::PatternT8R8,
1198                TrigCondition::try_from(&64_u8).unwrap()
1199            )
1200        }
1201    }
1202    mod get_value {
1203        use crate::settings::TrigCondition;
1204
1205        #[test]
1206        fn none() {
1207            assert_eq!(TrigCondition::None as u8, 0)
1208        }
1209        #[test]
1210        fn fill() {
1211            assert_eq!(TrigCondition::Fill as u8, 1)
1212        }
1213        #[test]
1214        fn notfill() {
1215            assert_eq!(TrigCondition::NotFill as u8, 2)
1216        }
1217        #[test]
1218        fn pre() {
1219            assert_eq!(TrigCondition::Pre as u8, 3)
1220        }
1221        #[test]
1222        fn notpre() {
1223            assert_eq!(TrigCondition::NotPre as u8, 4)
1224        }
1225        #[test]
1226        fn nei() {
1227            assert_eq!(TrigCondition::Nei as u8, 5)
1228        }
1229        #[test]
1230        fn notnei() {
1231            assert_eq!(TrigCondition::NotNei as u8, 6)
1232        }
1233        #[test]
1234        fn first() {
1235            assert_eq!(TrigCondition::First as u8, 7)
1236        }
1237        #[test]
1238        fn notfirst() {
1239            assert_eq!(TrigCondition::NotFirst as u8, 8)
1240        }
1241        #[test]
1242        fn perc1() {
1243            assert_eq!(TrigCondition::Percent1 as u8, 9)
1244        }
1245        #[test]
1246        fn perc2() {
1247            assert_eq!(TrigCondition::Percent2 as u8, 10)
1248        }
1249        #[test]
1250        fn perc4() {
1251            assert_eq!(TrigCondition::Percent4 as u8, 11)
1252        }
1253        #[test]
1254        fn perc6() {
1255            assert_eq!(TrigCondition::Percent6 as u8, 12)
1256        }
1257        #[test]
1258        fn perc9() {
1259            assert_eq!(TrigCondition::Percent9 as u8, 13)
1260        }
1261        #[test]
1262        fn perc13() {
1263            assert_eq!(TrigCondition::Percent13 as u8, 14)
1264        }
1265        #[test]
1266        fn perc19() {
1267            assert_eq!(TrigCondition::Percent19 as u8, 15)
1268        }
1269        #[test]
1270        fn perc25() {
1271            assert_eq!(TrigCondition::Percent25 as u8, 16)
1272        }
1273        #[test]
1274        fn perc33() {
1275            assert_eq!(TrigCondition::Percent33 as u8, 17)
1276        }
1277        #[test]
1278        fn perc41() {
1279            assert_eq!(TrigCondition::Percent41 as u8, 18)
1280        }
1281        #[test]
1282        fn perc50() {
1283            assert_eq!(TrigCondition::Percent50 as u8, 19)
1284        }
1285        #[test]
1286        fn perc59() {
1287            assert_eq!(TrigCondition::Percent59 as u8, 20)
1288        }
1289        #[test]
1290        fn perc67() {
1291            assert_eq!(TrigCondition::Percent67 as u8, 21)
1292        }
1293        #[test]
1294        fn perc75() {
1295            assert_eq!(TrigCondition::Percent75 as u8, 22)
1296        }
1297        #[test]
1298        fn perc81() {
1299            assert_eq!(TrigCondition::Percent81 as u8, 23)
1300        }
1301        #[test]
1302        fn perc87() {
1303            assert_eq!(TrigCondition::Percent87 as u8, 24)
1304        }
1305        #[test]
1306        fn perc91() {
1307            assert_eq!(TrigCondition::Percent91 as u8, 25)
1308        }
1309        #[test]
1310        fn perc94() {
1311            assert_eq!(TrigCondition::Percent94 as u8, 26)
1312        }
1313        #[test]
1314        fn perc96() {
1315            assert_eq!(TrigCondition::Percent96 as u8, 27)
1316        }
1317        #[test]
1318        fn perc98() {
1319            assert_eq!(TrigCondition::Percent98 as u8, 28)
1320        }
1321        #[test]
1322        fn perc99() {
1323            assert_eq!(TrigCondition::Percent99 as u8, 29)
1324        }
1325        #[test]
1326        fn pat_t1r2() {
1327            assert_eq!(TrigCondition::PatternT1R2 as u8, 30)
1328        }
1329        #[test]
1330        fn pat_t2r2() {
1331            assert_eq!(TrigCondition::PatternT2R2 as u8, 31)
1332        }
1333        #[test]
1334        fn pat_t1r3() {
1335            assert_eq!(TrigCondition::PatternT1R3 as u8, 32)
1336        }
1337        #[test]
1338        fn pat_t2r3() {
1339            assert_eq!(TrigCondition::PatternT2R3 as u8, 33)
1340        }
1341        #[test]
1342        fn pat_t3r3() {
1343            assert_eq!(TrigCondition::PatternT3R3 as u8, 34)
1344        }
1345
1346        #[test]
1347        fn pat_t1r4() {
1348            assert_eq!(TrigCondition::PatternT1R4 as u8, 35)
1349        }
1350        #[test]
1351        fn pat_t2r4() {
1352            assert_eq!(TrigCondition::PatternT2R4 as u8, 36)
1353        }
1354        #[test]
1355        fn pat_t3r4() {
1356            assert_eq!(TrigCondition::PatternT3R4 as u8, 37)
1357        }
1358        #[test]
1359        fn pat_t4r4() {
1360            assert_eq!(TrigCondition::PatternT4R4 as u8, 38)
1361        }
1362
1363        #[test]
1364        fn pat_t1r5() {
1365            assert_eq!(TrigCondition::PatternT1R5 as u8, 39)
1366        }
1367        #[test]
1368        fn pat_t2r5() {
1369            assert_eq!(TrigCondition::PatternT2R5 as u8, 40)
1370        }
1371        #[test]
1372        fn pat_t3r5() {
1373            assert_eq!(TrigCondition::PatternT3R5 as u8, 41)
1374        }
1375        #[test]
1376        fn pat_t4r5() {
1377            assert_eq!(TrigCondition::PatternT4R5 as u8, 42)
1378        }
1379        #[test]
1380        fn pat_t5r5() {
1381            assert_eq!(TrigCondition::PatternT5R5 as u8, 43)
1382        }
1383
1384        #[test]
1385        fn pat_t1r6() {
1386            assert_eq!(TrigCondition::PatternT1R6 as u8, 44)
1387        }
1388        #[test]
1389        fn pat_t2r6() {
1390            assert_eq!(TrigCondition::PatternT2R6 as u8, 45)
1391        }
1392        #[test]
1393        fn pat_t3r6() {
1394            assert_eq!(TrigCondition::PatternT3R6 as u8, 46)
1395        }
1396        #[test]
1397        fn pat_t4r6() {
1398            assert_eq!(TrigCondition::PatternT4R6 as u8, 47)
1399        }
1400        #[test]
1401        fn pat_t5r6() {
1402            assert_eq!(TrigCondition::PatternT5R6 as u8, 48)
1403        }
1404        #[test]
1405        fn pat_t6r6() {
1406            assert_eq!(TrigCondition::PatternT6R6 as u8, 49)
1407        }
1408
1409        #[test]
1410        fn pat_t1r7() {
1411            assert_eq!(TrigCondition::PatternT1R7 as u8, 50)
1412        }
1413        #[test]
1414        fn pat_t2r7() {
1415            assert_eq!(TrigCondition::PatternT2R7 as u8, 51)
1416        }
1417        #[test]
1418        fn pat_t3r7() {
1419            assert_eq!(TrigCondition::PatternT3R7 as u8, 52)
1420        }
1421        #[test]
1422        fn pat_t4r7() {
1423            assert_eq!(TrigCondition::PatternT4R7 as u8, 53)
1424        }
1425        #[test]
1426        fn pat_t5r7() {
1427            assert_eq!(TrigCondition::PatternT5R7 as u8, 54)
1428        }
1429        #[test]
1430        fn pat_t6r7() {
1431            assert_eq!(TrigCondition::PatternT6R7 as u8, 55)
1432        }
1433        #[test]
1434        fn pat_t7r7() {
1435            assert_eq!(TrigCondition::PatternT7R7 as u8, 56)
1436        }
1437
1438        #[test]
1439        fn pat_t1r8() {
1440            assert_eq!(TrigCondition::PatternT1R8 as u8, 57)
1441        }
1442        #[test]
1443        fn pat_t2r8() {
1444            assert_eq!(TrigCondition::PatternT2R8 as u8, 58)
1445        }
1446        #[test]
1447        fn pat_t3r8() {
1448            assert_eq!(TrigCondition::PatternT3R8 as u8, 59)
1449        }
1450        #[test]
1451        fn pat_t4r8() {
1452            assert_eq!(TrigCondition::PatternT4R8 as u8, 60)
1453        }
1454        #[test]
1455        fn pat_t5r8() {
1456            assert_eq!(TrigCondition::PatternT5R8 as u8, 61)
1457        }
1458        #[test]
1459        fn pat_t6r8() {
1460            assert_eq!(TrigCondition::PatternT6R8 as u8, 62)
1461        }
1462        #[test]
1463        fn pat_t7r8() {
1464            assert_eq!(TrigCondition::PatternT7R8 as u8, 63)
1465        }
1466        #[test]
1467        fn pat_t8r8() {
1468            assert_eq!(TrigCondition::PatternT8R8 as u8, 64)
1469        }
1470    }
1471}
1472
1473/// MIDI Channel options in Project Settings Menu
1474/// (should only be use where `Disabled` is an option in the menu!).
1475#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, IntoSigneds)]
1476#[repr(i8)]
1477pub enum MidiChannel {
1478    /// No MIDI Channel selected -- Project Menu -> Control -> Midi -> Sync
1479    #[default]
1480    Disabled = -1,
1481    // 0 is skipped
1482    /// MIDI CH 1
1483    One = 1,
1484    /// MIDI CH 2
1485    Two = 2,
1486    /// MIDI CH 3
1487    Three = 3,
1488    /// MIDI CH 4
1489    Four = 4,
1490    /// MIDI CH 5
1491    Five = 5,
1492    /// MIDI CH 6
1493    Six = 6,
1494    /// MIDI CH 7
1495    Seven = 7,
1496    /// MIDI CH 8
1497    Eight = 8,
1498    /// MIDI CH 9
1499    Nine = 9,
1500    /// MIDI CH 10
1501    Ten = 10,
1502    /// MIDI CH 11
1503    Eleven = 11,
1504    /// MIDI CH 12
1505    Twelve = 12,
1506    /// MIDI CH 13
1507    Thirteen = 13,
1508    /// MIDI CH 14
1509    Fourteen = 14,
1510    /// MIDI CH 15
1511    Fifteen = 15,
1512    /// MIDI CH 16
1513    Sixteen = 16,
1514}
1515
1516#[enum_try_from_i32_to_signed_types]
1517impl TryFrom<i32> for MidiChannel {
1518    type Error = InvalidValueError;
1519    fn try_from(value: i32) -> Result<Self, Self::Error> {
1520        match value {
1521            -1 => Ok(Self::Disabled),
1522            1 => Ok(Self::One),
1523            2 => Ok(Self::Two),
1524            3 => Ok(Self::Three),
1525            4 => Ok(Self::Four),
1526            5 => Ok(Self::Five),
1527            6 => Ok(Self::Six),
1528            7 => Ok(Self::Seven),
1529            8 => Ok(Self::Eight),
1530            9 => Ok(Self::Nine),
1531            10 => Ok(Self::Ten),
1532            11 => Ok(Self::Eleven),
1533            12 => Ok(Self::Twelve),
1534            13 => Ok(Self::Thirteen),
1535            14 => Ok(Self::Fourteen),
1536            15 => Ok(Self::Fifteen),
1537            16 => Ok(Self::Sixteen),
1538            _ => Err(InvalidValueError::MidiChannel),
1539        }
1540    }
1541}
1542
1543#[cfg(test)]
1544#[allow(unused_imports)]
1545mod test_spec {
1546
1547    mod value {
1548        use crate::settings::MidiChannel;
1549
1550        #[test]
1551        fn test_disabled() {
1552            assert_eq!(MidiChannel::Disabled as i8, -1);
1553        }
1554        #[test]
1555        fn test_1() {
1556            assert_eq!(MidiChannel::One as i8, 1);
1557        }
1558        #[test]
1559        fn test_2() {
1560            assert_eq!(MidiChannel::Two as i8, 2);
1561        }
1562        #[test]
1563        fn test_3() {
1564            assert_eq!(MidiChannel::Three as i8, 3);
1565        }
1566        #[test]
1567        fn test_4() {
1568            assert_eq!(MidiChannel::Four as i8, 4);
1569        }
1570        #[test]
1571        fn test_5() {
1572            assert_eq!(MidiChannel::Five as i8, 5);
1573        }
1574        #[test]
1575        fn test_6() {
1576            assert_eq!(MidiChannel::Six as i8, 6);
1577        }
1578        #[test]
1579        fn test_7() {
1580            assert_eq!(MidiChannel::Seven as i8, 7);
1581        }
1582        #[test]
1583        fn test_8() {
1584            assert_eq!(MidiChannel::Eight as i8, 8);
1585        }
1586        #[test]
1587        fn test_9() {
1588            assert_eq!(MidiChannel::Nine as i8, 9);
1589        }
1590        #[test]
1591        fn test_10() {
1592            assert_eq!(MidiChannel::Ten as i8, 10);
1593        }
1594        #[test]
1595        fn test_11() {
1596            assert_eq!(MidiChannel::Eleven as i8, 11);
1597        }
1598        #[test]
1599        fn test_12() {
1600            assert_eq!(MidiChannel::Twelve as i8, 12);
1601        }
1602        #[test]
1603        fn test_13() {
1604            assert_eq!(MidiChannel::Thirteen as i8, 13);
1605        }
1606        #[test]
1607        fn test_14() {
1608            assert_eq!(MidiChannel::Fourteen as i8, 14);
1609        }
1610        #[test]
1611        fn test_15() {
1612            assert_eq!(MidiChannel::Fifteen as i8, 15);
1613        }
1614        #[test]
1615        fn test_16() {
1616            assert_eq!(MidiChannel::Sixteen as i8, 16);
1617        }
1618    }
1619
1620    mod from_value {
1621
1622        use crate::settings::MidiChannel;
1623
1624        #[test]
1625        fn test_error_1() {
1626            assert!(MidiChannel::try_from(&100_i8).is_err());
1627        }
1628        #[test]
1629        fn test_error_2() {
1630            assert!(MidiChannel::try_from(&0_i8).is_err());
1631        }
1632        #[test]
1633        fn test_disabled() {
1634            assert_eq!(
1635                MidiChannel::Disabled,
1636                MidiChannel::try_from(&-1_i8).unwrap()
1637            );
1638        }
1639        #[test]
1640        fn test_1() {
1641            assert_eq!(MidiChannel::One, MidiChannel::try_from(&1_i8).unwrap());
1642        }
1643        #[test]
1644        fn test_2() {
1645            assert_eq!(MidiChannel::Two, MidiChannel::try_from(&2_i8).unwrap());
1646        }
1647        #[test]
1648        fn test_3() {
1649            assert_eq!(MidiChannel::Three, MidiChannel::try_from(&3_i8).unwrap());
1650        }
1651        #[test]
1652        fn test_4() {
1653            assert_eq!(MidiChannel::Four, MidiChannel::try_from(&4_i8).unwrap());
1654        }
1655        #[test]
1656        fn test_5() {
1657            assert_eq!(MidiChannel::Five, MidiChannel::try_from(&5_i8).unwrap());
1658        }
1659        #[test]
1660        fn test_6() {
1661            assert_eq!(MidiChannel::Six, MidiChannel::try_from(&6_i8).unwrap());
1662        }
1663        #[test]
1664        fn test_7() {
1665            assert_eq!(MidiChannel::Seven, MidiChannel::try_from(&7_i8).unwrap());
1666        }
1667        #[test]
1668        fn test_8() {
1669            assert_eq!(MidiChannel::Eight, MidiChannel::try_from(&8_i8).unwrap());
1670        }
1671        #[test]
1672        fn test_9() {
1673            assert_eq!(MidiChannel::Nine, MidiChannel::try_from(&9_i8).unwrap());
1674        }
1675        #[test]
1676        fn test_10() {
1677            assert_eq!(MidiChannel::Ten, MidiChannel::try_from(&10_i8).unwrap());
1678        }
1679        #[test]
1680        fn test_11() {
1681            assert_eq!(MidiChannel::Eleven, MidiChannel::try_from(&11_i8).unwrap());
1682        }
1683        #[test]
1684        fn test_12() {
1685            assert_eq!(MidiChannel::Twelve, MidiChannel::try_from(&12_i8).unwrap());
1686        }
1687        #[test]
1688        fn test_13() {
1689            assert_eq!(
1690                MidiChannel::Thirteen,
1691                MidiChannel::try_from(&13_i8).unwrap()
1692            );
1693        }
1694        #[test]
1695        fn test_14() {
1696            assert_eq!(
1697                MidiChannel::Fourteen,
1698                MidiChannel::try_from(&14_i8).unwrap()
1699            );
1700        }
1701        #[test]
1702        fn test_15() {
1703            assert_eq!(MidiChannel::Fifteen, MidiChannel::try_from(&15_i8).unwrap());
1704        }
1705        #[test]
1706        fn test_16() {
1707            assert_eq!(MidiChannel::Sixteen, MidiChannel::try_from(&16_i8).unwrap());
1708        }
1709    }
1710}
1711
1712/// Slot's machine type (cannot access flex samples for a static machine etc).
1713#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq, Hash)]
1714pub enum SlotType {
1715    /// Static machine slot
1716    Static,
1717    /// Flex machine slot
1718    Flex,
1719}
1720
1721impl SlotType {
1722    pub fn other(&self) -> Self {
1723        match self {
1724            Self::Static => Self::Flex,
1725            Self::Flex => Self::Static,
1726        }
1727    }
1728}
1729
1730impl TryFrom<String> for SlotType {
1731    type Error = InvalidValueError;
1732    fn try_from(value: String) -> Result<Self, Self::Error> {
1733        match value.to_ascii_uppercase().as_str() {
1734            "STATIC" => Ok(SlotType::Static),
1735            "FLEX" => Ok(SlotType::Flex),
1736            _ => Err(InvalidValueError::SlotType),
1737        }
1738    }
1739}
1740
1741impl TryFrom<&str> for SlotType {
1742    type Error = InvalidValueError;
1743    fn try_from(value: &str) -> Result<Self, Self::Error> {
1744        Self::try_from(value.to_string())
1745    }
1746}
1747
1748impl Display for SlotType {
1749    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1750        let str = match self {
1751            SlotType::Static => "STATIC".to_string(),
1752            SlotType::Flex => "FLEX".to_string(),
1753        };
1754        write!(f, "{str}")
1755    }
1756}
1757
1758impl From<SlotType> for String {
1759    fn from(value: SlotType) -> Self {
1760        value.to_string()
1761    }
1762}
1763
1764#[cfg(test)]
1765mod slot_type {
1766    mod value {
1767        use crate::settings::SlotType;
1768
1769        #[test]
1770        fn test_static() {
1771            assert_eq!(SlotType::Static.to_string(), "STATIC");
1772        }
1773        #[test]
1774        fn test_flex() {
1775            assert_eq!(SlotType::Flex.to_string(), "FLEX");
1776        }
1777    }
1778
1779    mod from_value {
1780        use crate::settings::SlotType;
1781
1782        #[test]
1783        fn test_error() {
1784            assert!(SlotType::try_from("SOME INCORRECT STRING").is_err());
1785        }
1786
1787        #[test]
1788        fn test_static_upper() {
1789            assert_eq!(SlotType::Static, SlotType::try_from("STATIC").unwrap(),);
1790        }
1791
1792        #[test]
1793        fn test_static_lower() {
1794            assert_eq!(SlotType::Static, SlotType::try_from("static").unwrap(),);
1795        }
1796
1797        #[test]
1798        fn test_flex_upper() {
1799            assert_eq!(SlotType::Flex, SlotType::try_from("FLEX").unwrap(),);
1800        }
1801
1802        #[test]
1803        fn test_flex_lower() {
1804            assert_eq!(SlotType::Flex, SlotType::try_from("flex").unwrap(),);
1805        }
1806    }
1807}