1use crate::prelude::*;
6
7pub(crate) trait SplitChecked: Sized {
8 fn split_checked(&mut self, at: usize) -> Option<Self>;
9}
10impl<'a> SplitChecked for &'a [u8] {
11 #[inline]
12 fn split_checked(&mut self, at: usize) -> Option<&'a [u8]> {
13 if at > self.len() {
14 None
15 } else {
16 let (extracted, remainder) = self.split_at(at);
17 *self = remainder;
18 Some(extracted)
19 }
20 }
21}
22
23pub(crate) trait IntRead: Sized {
25 fn read(data: &mut &[u8]) -> StdResult<Self, &'static ErrorKind>;
27}
28pub(crate) trait IntReadBottom7: Sized {
31 fn read_u7(data: &mut &[u8]) -> StdResult<Self, &'static ErrorKind>;
33}
34
35macro_rules! impl_read_int {
37 {$( $int:ty ),*} => {
38 $(
39 impl IntRead for $int {
40 #[inline]
41 fn read(raw: &mut &[u8]) -> StdResult<$int, &'static ErrorKind> {
42 let bytes = raw.split_checked(mem::size_of::<$int>())
43 .ok_or(err_invalid!("failed to read the expected integer"))?;
44 Ok(bytes.iter().fold(0,|mut acc,byte| {
45 acc=acc.checked_shl(8).unwrap_or(0);
46 acc|=*byte as $int;
47 acc
48 }))
49 }
50 }
51 )*
52 }
53}
54impl_read_int! {u8,u16,u32}
55
56macro_rules! int_feature {
58 { $name:ident ; $inner:tt : read_u7 } => {
59 impl IntReadBottom7 for $name {
60 fn read_u7(raw: &mut &[u8]) -> StdResult<$name, &'static ErrorKind> {
61 let bytes = raw.split_checked(mem::size_of::<$inner>())
62 .ok_or(err_invalid!("failed to read the expected integer"))?;
63 if cfg!(feature = "strict") {
64 ensure!(bytes.iter().all(|byte| bit_range!(*byte, 7..8)==0), err_malformed!("invalid byte with top bit set"));
65 }
66 let raw = bytes.iter().fold(0, |mut acc,byte| {
67 acc <<= 7;
68 acc |= bit_range!(*byte, 0..7) as $inner;
69 acc
70 });
71 Ok(if cfg!(feature = "strict") {
72 Self::try_from(raw).ok_or(err_malformed!(stringify!("expected " $name ", found " $inner)))?
73 }else{
74 Self::from(raw)
76 })
77 }
78 }
79 };
80 { $name:ident ; $inner:tt : read } => {
81 impl IntRead for $name {
82 #[inline]
83 fn read(raw: &mut &[u8]) -> StdResult<Self, &'static ErrorKind> {
84 let raw = $inner::read(raw)?;
85 if cfg!(feature = "strict") {
86 Ok(Self::try_from(raw).ok_or(err_malformed!(concat!("expected ", stringify!($name), ", found ", stringify!($inner))))?)
87 }else{
88 Ok(Self::from(raw))
90 }
91 }
92 }
93 };
94}
95macro_rules! restricted_int {
96 {$(#[$attr:meta])* $name:ident : $inner:tt => $bits:expr ; $( $feature:tt )* } => {
97 $(#[$attr])*
98 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
99 #[repr(transparent)]
100 #[allow(non_camel_case_types)]
101 pub struct $name($inner);
102 impl From<$inner> for $name {
103 #[inline]
105 fn from(raw: $inner) -> $name {
106 $name::from_int_lossy(raw)
107 }
108 }
109 impl From<$name> for $inner {
110 #[inline]
111 fn from(restricted: $name) -> $inner {restricted.0}
112 }
113 impl fmt::Display for $name {
114 #[inline]
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 fmt::Display::fmt(&self.0, f)
117 }
118 }
119 impl $name {
120 const MASK: $inner = (1 << $bits) - 1;
121
122 #[inline]
124 pub const fn max_value() -> $name {
125 $name (Self::MASK)
126 }
127
128 #[inline]
131 pub const fn new(raw: $inner) -> $name {
132 $name (raw & Self::MASK)
133 }
134
135 #[inline]
138 pub const fn from_int_lossy(raw: $inner) -> $name {
139 $name (raw & Self::MASK)
140 }
141
142 #[inline]
145 pub fn try_from(raw: $inner) -> Option<$name> {
146 if raw <= Self::MASK {
147 Some($name(raw))
148 }else{
149 None
150 }
151 }
152
153 #[inline]
156 pub fn as_int(self) -> $inner {
157 Into::into(self)
158 }
159
160 #[inline]
163 pub fn slice_try_from_int(raw: &[$inner]) -> Option<&[$name]> {
164 for &int in raw {
165 if int > Self::MASK {
166 return None;
167 }
168 }
169 unsafe {
170 Some(Self::slice_from_int_unchecked(raw))
171 }
172 }
173
174 #[inline]
178 pub fn slice_from_int(raw: &[$inner]) -> &[$name] {
179 let first_oob = raw
180 .iter()
181 .position(|&b| b > Self::MASK)
182 .unwrap_or(raw.len());
183 unsafe {
184 Self::slice_from_int_unchecked(&raw[..first_oob])
185 }
186 }
187
188 #[inline]
194 pub unsafe fn slice_from_int_unchecked(raw: &[$inner]) -> &[$name] {
195 &*( raw as *const [$inner] as *const [$name] )
196 }
197
198 #[inline]
201 pub fn slice_try_from_int_mut(raw: &mut [$inner]) -> Option<&mut [$name]> {
202 for &int in raw.iter() {
203 if int > Self::MASK {
204 return None;
205 }
206 }
207 unsafe {
208 Some(Self::slice_from_int_unchecked_mut(raw))
209 }
210 }
211
212 #[inline]
216 pub fn slice_from_int_mut(raw: &mut [$inner]) -> &mut [$name] {
217 let first_oob = raw
218 .iter()
219 .position(|&b| b > Self::MASK)
220 .unwrap_or(raw.len());
221 unsafe {
222 Self::slice_from_int_unchecked_mut(&mut raw[..first_oob])
223 }
224 }
225
226 #[inline]
232 pub unsafe fn slice_from_int_unchecked_mut(raw: &mut [$inner]) -> &mut [$name] {
233 &mut *( raw as *mut [$inner] as *mut [$name] )
234 }
235
236 #[inline]
240 pub fn slice_as_int(slice: &[$name]) -> &[$inner] {
241 unsafe { &*(slice as *const [$name] as *const [$inner]) }
242 }
243
244 #[allow(dead_code)]
245 #[inline]
246 pub(crate) fn check_int(raw: $inner) -> StdResult<$name, &'static ErrorKind> {
247 Self::try_from(raw).ok_or_else(
248 || err_invalid!("invalid integer with top bits set")
249 )
250 }
251 }
252 impl PartialEq<$inner> for $name {
253 fn eq(&self, rhs: &$inner) -> bool {
254 self.as_int() == *rhs
255 }
256 }
257 impl PartialOrd<$inner> for $name {
258 fn partial_cmp(&self, rhs: &$inner) -> Option<core::cmp::Ordering> {
259 Some(self.as_int().cmp(rhs))
260 }
261 }
262 impl PartialEq<$name> for $inner {
263 fn eq(&self, rhs: &$name) -> bool {
264 *self == rhs.as_int()
265 }
266 }
267 impl PartialOrd<$name> for $inner {
268 fn partial_cmp(&self, rhs: &$name) -> Option<core::cmp::Ordering> {
269 Some(self.cmp(&rhs.as_int()))
270 }
271 }
272 impl core::ops::Add for $name {
273 type Output = Self;
274 fn add(self, other: Self) -> Self {
275 Self::new(self.as_int() + other.as_int())
276 }
277 }
278 impl core::ops::Sub for $name {
279 type Output = Self;
280 fn sub(self, other: Self) -> Self {
281 Self::new(self.as_int() - other.as_int())
282 }
283 }
284 impl core::ops::AddAssign for $name {
285 fn add_assign(&mut self, other: Self) {
286 *self = *self + other
287 }
288 }
289 impl core::ops::SubAssign for $name {
290 fn sub_assign(&mut self, other: Self) {
291 *self = *self - other
292 }
293 }
294
295 $( int_feature!{$name ; $inner : $feature} )*
296 };
297}
298restricted_int! {
299 u15: u16 => 15; read
303}
304restricted_int! {
305 u14: u16 => 14; read read_u7
309}
310restricted_int! {
311 u7: u8 => 7; read
315}
316restricted_int! {
317 u4: u8 => 4; read
321}
322restricted_int! {
323 u2: u8 => 2; read
327}
328restricted_int! {
329 u24: u32 => 24;
333}
334impl IntRead for u24 {
335 fn read(raw: &mut &[u8]) -> StdResult<u24, &'static ErrorKind> {
336 let bytes = raw
337 .split_checked(3)
338 .ok_or(err_invalid!("failed to read u24 bytes"))?;
339 Ok(u24::from(bytes.iter().fold(0, |mut acc, byte| {
341 acc <<= 8;
342 acc |= *byte as u32;
343 acc
344 })))
345 }
346}
347
348restricted_int! {
349 u28: u32 => 28;
351}
352impl IntReadBottom7 for u28 {
353 fn read_u7(raw: &mut &[u8]) -> StdResult<u28, &'static ErrorKind> {
354 let mut int: u32 = 0;
355 for _ in 0..4 {
356 let byte = match raw.split_checked(1) {
357 Some(slice) => slice[0],
358 None => {
359 if cfg!(feature = "strict") {
360 bail!(err_malformed!("unexpected eof while reading varlen int"))
361 } else {
362 break;
364 }
365 }
366 };
367 int <<= 7;
368 int |= bit_range!(byte, 0..7) as u32;
369 if bit_range!(byte, 7..8) == 0 {
370 return Ok(u28::from(int));
373 }
374 }
375 if cfg!(feature = "strict") {
376 Err(err_malformed!("varlen integer larger than 4 bytes"))
377 } else {
378 Ok(u28::from(int))
380 }
381 }
382}
383
384impl u28 {
385 pub(crate) fn write_varlen<W: Write>(&self, out: &mut W) -> WriteResult<W> {
386 let int = self.as_int();
387 let mut skipping = true;
388 for i in (0..4).rev() {
389 let byte = ((int >> (i * 7)) & 0x7F) as u8;
390 if skipping && byte == 0 && i != 0 {
391 } else {
393 skipping = false;
395 let byte = if i == 0 {
396 byte
398 } else {
399 byte | 0x80
401 };
402 out.write(&[byte])?;
403 }
404 }
405 Ok(())
406 }
407}
408
409pub(crate) fn read_varlen_slice<'a>(raw: &mut &'a [u8]) -> Result<&'a [u8]> {
411 let len = u28::read_u7(raw)
412 .context(err_invalid!("failed to read varlen slice length"))?
413 .as_int();
414 Ok(match raw.split_checked(len as usize) {
415 Some(slice) => slice,
416 None => {
417 if cfg!(feature = "strict") {
418 bail!(err_malformed!("incomplete varlen slice"))
419 } else {
420 mem::replace(raw, &[])
421 }
422 }
423 })
424}
425
426pub(crate) fn write_varlen_slice<W: Write>(slice: &[u8], out: &mut W) -> WriteResult<W> {
428 let len = u32::try_from(slice.len())
429 .ok()
430 .and_then(u28::try_from)
431 .ok_or_else(|| W::invalid_input("varlen slice exceeds 28 bits"))?;
432 len.write_varlen(out)?;
433 out.write(slice)?;
434 Ok(())
435}
436
437#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
439pub enum Format {
440 SingleTrack,
445 Parallel,
449 Sequential,
454}
455impl Format {
456 pub(crate) fn read(raw: &mut &[u8]) -> Result<Format> {
457 let format = u16::read(raw)?;
458 Ok(match format {
459 0 => Format::SingleTrack,
460 1 => Format::Parallel,
461 2 => Format::Sequential,
462 _ => bail!(err_invalid!("invalid smf format")),
463 })
464 }
465
466 pub(crate) fn encode(&self) -> [u8; 2] {
467 let code: u16 = match self {
468 Format::SingleTrack => 0,
469 Format::Parallel => 1,
470 Format::Sequential => 2,
471 };
472 code.to_be_bytes()
473 }
474}
475
476#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
479pub enum Timing {
480 Metrical(u15),
485 Timecode(Fps, u8),
488}
489impl Timing {
490 pub(crate) fn read(raw: &mut &[u8]) -> Result<Timing> {
491 let raw =
492 u16::read(raw).context(err_invalid!("unexpected eof when reading midi timing"))?;
493 if bit_range!(raw, 15..16) != 0 {
494 let fps = -(bit_range!(raw, 8..16) as i8);
496 let subframe = bit_range!(raw, 0..8) as u8;
497 Ok(Timing::Timecode(
498 Fps::from_int(fps as u8).ok_or(err_invalid!("invalid smpte fps"))?,
499 subframe,
500 ))
501 } else {
502 Ok(Timing::Metrical(u15::from(raw)))
504 }
505 }
506
507 pub(crate) fn encode(&self) -> [u8; 2] {
508 match self {
509 Timing::Metrical(ticksperbeat) => ticksperbeat.as_int().to_be_bytes(),
510 Timing::Timecode(framespersec, ticksperframe) => {
511 [(-(framespersec.as_int() as i8)) as u8, *ticksperframe]
512 }
513 }
514 }
515}
516
517#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
527pub struct SmpteTime {
528 hour: u8,
529 minute: u8,
530 second: u8,
531 frame: u8,
532 subframe: u8,
533 fps: Fps,
534}
535impl SmpteTime {
536 #[inline]
538 pub fn new(
539 hour: u8,
540 minute: u8,
541 second: u8,
542 frame: u8,
543 subframe: u8,
544 fps: Fps,
545 ) -> Option<SmpteTime> {
546 macro_rules! check {
547 ($cond:expr) => {{
548 if !{ $cond } {
549 return None;
550 }
551 }};
552 }
553 check!(hour < 24);
554 check!(minute < 60);
555 check!(second < 60);
556 check!(frame < fps.as_int());
557 check!(subframe < 100);
558 Some(SmpteTime {
559 hour,
560 minute,
561 second,
562 frame,
563 subframe,
564 fps,
565 })
566 }
567
568 #[inline]
570 pub fn hour(&self) -> u8 {
571 self.hour
572 }
573
574 #[inline]
576 pub fn minute(&self) -> u8 {
577 self.minute
578 }
579
580 #[inline]
582 pub fn second(&self) -> u8 {
583 self.second
584 }
585
586 #[inline]
589 pub fn frame(&self) -> u8 {
590 self.frame
591 }
592
593 #[inline]
595 pub fn subframe(&self) -> u8 {
596 self.subframe
597 }
598
599 #[inline]
601 pub fn fps(&self) -> Fps {
602 self.fps
603 }
604
605 #[inline]
609 pub fn second_f32(&self) -> f32 {
610 self.second as f32
611 + ((self.frame as f32 + self.subframe as f32 / 100.0) / self.fps.as_f32())
612 }
613
614 pub(crate) fn read(raw: &mut &[u8]) -> Result<SmpteTime> {
615 let data = raw
616 .split_checked(5)
617 .ok_or(err_invalid!("failed to read smpte time data"))?;
618 let hour_fps = data[0];
619 let (hour, fps) = (bit_range!(hour_fps, 0..5), bit_range!(hour_fps, 5..7));
620 let fps = Fps::from_code(u2::from(fps));
621 let minute = data[1];
622 let second = data[2];
623 let frame = data[3];
624 let subframe = data[4];
625 Ok(SmpteTime::new(hour, minute, second, frame, subframe, fps)
626 .ok_or(err_invalid!("invalid smpte time"))?)
627 }
628
629 pub(crate) fn encode(&self) -> [u8; 5] {
630 let hour_fps = self.hour() | self.fps().as_code().as_int() << 5;
631 [
632 hour_fps,
633 self.minute(),
634 self.second(),
635 self.frame(),
636 self.subframe(),
637 ]
638 }
639}
640
641#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
643pub enum Fps {
644 Fps24,
646 Fps25,
648 Fps29,
652 Fps30,
654}
655impl Fps {
656 pub(crate) fn from_code(code: u2) -> Fps {
658 match code.as_int() {
659 0 => Fps::Fps24,
660 1 => Fps::Fps25,
661 2 => Fps::Fps29,
662 3 => Fps::Fps30,
663 _ => unreachable!(),
664 }
665 }
666
667 pub(crate) fn as_code(self) -> u2 {
669 u2::from(match self {
670 Fps::Fps24 => 0,
671 Fps::Fps25 => 1,
672 Fps::Fps29 => 2,
673 Fps::Fps30 => 3,
674 })
675 }
676
677 #[inline]
679 pub fn from_int(raw: u8) -> Option<Fps> {
680 Some(match raw {
681 24 => Fps::Fps24,
682 25 => Fps::Fps25,
683 29 => Fps::Fps29,
684 30 => Fps::Fps30,
685 _ => return None,
686 })
687 }
688
689 #[inline]
691 pub fn as_int(self) -> u8 {
692 match self {
693 Fps::Fps24 => 24,
694 Fps::Fps25 => 25,
695 Fps::Fps29 => 29,
696 Fps::Fps30 => 30,
697 }
698 }
699
700 #[inline]
702 pub fn as_f32(self) -> f32 {
703 match self.as_int() {
704 24 => 24.0,
705 25 => 25.0,
706 29 => 30.0 / 1.001,
707 30 => 30.0,
708 _ => unreachable!(),
709 }
710 }
711}
712impl From<Fps> for f32 {
713 fn from(x: Fps) -> Self {
714 x.as_f32()
715 }
716}
717impl From<Fps> for u8 {
718 fn from(x: Fps) -> Self {
719 x.as_int()
720 }
721}