1use crate::error::OutOfRangeError;
5pub(crate) use bitflags::bitflags;
6use std::convert::TryFrom;
7use std::fmt::{self, Debug};
8
9
10macro_rules! ranged_u8_newtype {
11 ( $name: ident, $low: literal ..= $high: literal ) => {
12 #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
13 pub struct $name(u8);
14
15 impl $name {
16 pub(crate) fn as_u8(self) -> u8 {
17 self.0
18 }
19 }
20
21 impl TryFrom<u8> for $name {
22 type Error = OutOfRangeError<$low, $high>;
23
24 fn try_from(raw: u8) -> Result<Self, Self::Error> {
25 if ($low..=$high).contains(&raw) {
26 Ok($name(raw))
27 } else {
28 Err(OutOfRangeError(raw))
29 }
30 }
31 }
32
33 impl From<$name> for u8 {
34 fn from(ranged: $name) -> u8 {
35 ranged.as_u8()
36 }
37 }
38
39 impl Debug for $name {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 Debug::fmt(&self.as_u8(), f)
42 }
43 }
44 };
45}
46
47ranged_u8_newtype!(InstrumentId, 0..=98);
51ranged_u8_newtype!(PatternId, 0..=199);
52ranged_u8_newtype!(SampleId, 0..=98);
53
54
55pub trait Get<I> {
56 type Output;
57 fn get(&self, index: I) -> Option<&Self::Output>;
58}
59
60impl<I, C> Get<&I> for C
61where
62 C: Get<I>,
63 I: Copy,
64{
65 type Output = <C as Get<I>>::Output;
66 fn get(&self, index: &I) -> Option<&Self::Output> {
67 self.get(*index)
68 }
69}
70
71macro_rules! impl_index_from_get {
72 ( $for: ty, $idx: ty ) => {
73 impl ::std::ops::Index<$idx> for $for {
74 type Output = <$for as $crate::data::Get<$idx>>::Output;
75 fn index(&self, index: $idx) -> &Self::Output {
76 self.get(index)
77 .unwrap_or_else(|| panic!("{} index {:?} out of range", ::std::any::type_name::<$idx>(), &index))
78 }
79 }
80
81 impl ::std::ops::Index<&$idx> for $for {
82 type Output = <$for as $crate::data::Get<$idx>>::Output;
83 fn index(&self, index: &$idx) -> &Self::Output {
84 self.get(index)
85 .unwrap_or_else(|| panic!("{} index {:?} out of range", ::std::any::type_name::<$idx>(), &index))
86 }
87 }
88 };
89}
90
91
92mod channel;
93mod envelope;
94mod instrument;
95mod module;
96mod pattern;
97mod sample;
98mod util;
99
100pub use channel::*;
101pub use envelope::*;
102pub use instrument::*;
103pub use module::*;
104pub use pattern::*;
105pub use sample::*;
106pub use util::*;