#![forbid(unsafe_code)]
#![cfg_attr(not(any(test, feature = "std")), no_std)]
extern crate alloc;
macro_rules! bail {
($err:expr) => {{
return Err($err.into());
}};
}
macro_rules! ensure {
($cond:expr, $err:expr) => {{
if !$cond {
bail!($err)
}
}};
}
mod error {
use core::fmt;
use failure::Fail;
#[cfg(all(debug_assertions, feature = "std"))]
mod error_impl {
use super::{Error, ErrorExt, ErrorKind};
use failure::{Backtrace, Context, Fail};
pub type ErrorInner = Context<ErrorKind>;
impl ErrorExt for Error {
fn kind(&self) -> ErrorKind {
*self.inner.get_context()
}
fn chain_ctx(self, ctx: ErrorKind) -> Error {
Error {
inner: Fail::context(self, ctx),
}
}
}
impl Fail for Error {
fn cause(&self) -> Option<&dyn Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
inner: Context::new(kind),
}
}
}
}
#[cfg(not(all(debug_assertions, feature = "std")))]
mod error_impl {
use super::{Error, ErrorExt, ErrorKind};
use failure::Fail;
pub type ErrorInner = ErrorKind;
impl Fail for Error {}
impl ErrorExt for Error {
fn kind(&self) -> ErrorKind {
self.inner
}
fn chain_ctx(self, ctx: ErrorKind) -> Error {
Error { inner: ctx }
}
}
impl From<ErrorKind> for Error {
fn from(inner: ErrorKind) -> Error {
Error { inner }
}
}
}
#[derive(Debug)]
pub struct Error {
inner: self::error_impl::ErrorInner,
}
impl Error {
pub fn kind(&self) -> ErrorKind {
ErrorExt::kind(self)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
trait ErrorExt {
fn kind(&self) -> ErrorKind;
fn chain_ctx(self, ctx: ErrorKind) -> Error;
}
#[derive(Copy, Clone, Debug, Fail)]
#[fail(display = "{}", _0)]
pub enum ErrorKind {
#[fail(display = "invalid smf file: {}", _0)]
Invalid(&'static str),
#[fail(display = "malformed smf file: {}", _0)]
Malformed(&'static str),
#[fail(display = "uncompliant smf file: {}", _0)]
Pedantic(&'static str),
}
impl ErrorKind {
pub fn message(&self) -> &'static str {
match *self {
ErrorKind::Invalid(msg) => msg,
ErrorKind::Malformed(msg) => msg,
ErrorKind::Pedantic(msg) => msg,
}
}
}
pub fn err_invalid(msg: &'static str) -> ErrorKind {
ErrorKind::Invalid(msg)
}
pub fn err_malformed(msg: &'static str) -> ErrorKind {
ErrorKind::Malformed(msg)
}
pub fn err_pedantic(msg: &'static str) -> ErrorKind {
ErrorKind::Pedantic(msg)
}
pub trait ResultExt<T> {
fn context(self, ctx: ErrorKind) -> StdResult<T, Error>;
}
impl<T> ResultExt<T> for StdResult<T, Error> {
fn context(self, ctx: ErrorKind) -> StdResult<T, Error> {
self.map_err(|err| err.chain_ctx(ctx))
}
}
impl<T> ResultExt<T> for StdResult<T, ErrorKind> {
fn context(self, ctx: ErrorKind) -> StdResult<T, Error> {
self.map_err(|errkind| Error::from(errkind).chain_ctx(ctx))
}
}
pub type Result<T> = StdResult<T, Error>;
pub use core::result::Result as StdResult;
}
mod prelude {
pub(crate) use crate::{
error::{
err_invalid, err_malformed, err_pedantic, ErrorKind, Result, ResultExt, StdResult,
},
primitive::{u14, u24, u28, u4, u7, IntRead, IntReadBottom7, SplitChecked},
};
pub use alloc::vec::Vec;
pub use core::{marker::PhantomData, mem, ops};
pub fn bit_range<T>(val: T, range: ops::Range<u32>) -> T
where
T: From<u8>
+ ops::Shr<u32, Output = T>
+ ops::Shl<u32, Output = T>
+ ops::Not<Output = T>
+ ops::BitAnd<Output = T>,
{
let mask = !((!T::from(0)) << (range.end - range.start));
(val >> range.start) & mask
}
}
mod event;
mod primitive;
mod smf;
pub use crate::{
error::{Error, ErrorKind},
event::{Event, EventKind, MetaMessage, MidiMessage},
primitive::{Format, Fps, SmpteTime, Timing},
smf::{Header, Smf, TrackIter, TrackRepr},
};
pub mod number {
pub use crate::primitive::{u14, u15, u24, u28, u4, u7};
}
#[cfg(test)]
mod test;