use crate::byte_iter::ByteIter;
use crate::core::vlq::Vlq;
use crate::error::{Context, Result};
use crate::scribe::Scribe;
use std::convert::TryFrom;
use std::io::{Read, Write};
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct SysexEvent {
t: SysexEventType,
data: Vec<u8>,
}
impl SysexEvent {
pub fn new(t: SysexEventType, data: Vec<u8>) -> Self {
Self { t, data }
}
pub fn sysex_type(&self) -> &SysexEventType {
&self.t
}
pub fn data(&self) -> &[u8] {
&self.data
}
pub(crate) fn parse<R: Read>(first_byte: u8, iter: &mut ByteIter<R>) -> Result<Self> {
iter.read_expect(first_byte).context(io!())?;
let t = match first_byte {
0xf0 => SysexEventType::F0,
0xf7 => SysexEventType::F7,
_ => invalid_file!("invalid sysex status byte {:#04X}", first_byte),
};
let length = iter.read_vlq_u32().context(io!())?;
let data = iter.read_n(length as usize).context(io!())?;
Ok(Self { t, data })
}
pub(crate) fn write<W: Write>(&self, w: &mut Scribe<W>) -> Result<()> {
write_u8!(w, self.t as u8)?;
let length =
u32::try_from(self.data.len()).context(ctx!(crate::error::ErrorType::StringTooLong))?;
w.write_all(&Vlq::new(length).to_bytes()).context(wr!())?;
w.write_all(&self.data).context(wr!())?;
Ok(())
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, Default)]
pub enum SysexEventType {
#[default]
F0 = 0xf0,
F7 = 0xf7,
}