ot-tools-io 0.11.2

A library crate for reading/writing binary data files used by the Elektron Octatrack DPS-1.
Documentation
/*
SPDX-License-Identifier: GPL-3.0-or-later
Copyright © 2024 Mike Robeson [dijksterhuis]
*/

//! standard library methods for generic new types (methods delegate to the inner type).

// requires Copy!
macro_rules! method_id {
    ($inner_t:ident, $id:ident) => {
        /// Returns an owned element of the array data
        ///
        /// # Panic-free
        ///
        /// This method is panic-free as the `id` type is guaranteed to never exceed the max index
        /// of the underlying array.
        pub fn id(self, id: &$id) -> $inner_t {
            self.0[id.as_index()]
        }
    };
}

macro_rules! method_id_ref {
    ($inner_t:ident, $id:ident) => {
        /// Returns a reference to an element of the array data
        ///
        /// # Panic-free
        ///
        /// This method is panic-free as the `id` type is guaranteed to never exceed the max index
        /// of the underlying array.
        pub fn id_ref(&self, id: &$id) -> &$inner_t {
            &self.0[id.as_index()]
        }
    };
}

macro_rules! method_id_mut {
    ($inner_t:ident, $id:ident) => {
        /// Returns a mutable reference to an element the array data
        ///
        /// # Panic-free
        ///
        /// This method is panic-free as the `id` type is guaranteed to never exceed the max index
        /// of the underlying array.
        pub fn id_mut(&mut self, id: &$id) -> &mut $inner_t {
            &mut self.0[id.as_index()]
        }
    };
}

/// Adds "unbox-ing" methods to a newtype that holds boxed array data
macro_rules! generic_newtype_unbox {
    ($name:ident, $n:expr) => {
        impl<T> $name<T> {
            /// Returns an owned `[T; 16]` by "un-boxing" (dereferencing) the data
            pub fn unbox(self) -> [T; $n] {
                *self.0
            }

            /// Returns a referenced `[T; 16]` by "un-boxing" (dereferencing) the data
            pub fn unbox_ref(&self) -> &[T; $n] {
                &*self.0
            }

            /// Returns a mutably referenced `[T; 16]` by "un-boxing" (dereferencing) the data
            pub fn unbox_mut(&mut self) -> &mut [T; $n] {
                &mut *self.0
            }
        }
    };
}

/// Adds ID based lookup methods to a newtype that holds array data that can be looked up with the
/// specified ID
macro_rules! generic_newtype_id_lookups {
    ($name:ident, $id:ident) => {
        impl<T> $name<T> {
            method_id_ref!(T, $id);
            method_id_mut!(T, $id);
        }

        impl<T: Copy> $name<T> {
            method_id!(T, $id);
        }
    };
}

/// Adds the [`AsRef`] trait to a newtype type
macro_rules! generic_newtype_asref {
    ($name:ident) => {
        impl<T> AsRef<$name<T>> for $name<T> {
            fn as_ref(&self) -> &$name<T> {
                self
            }
        }
    };
}

/// Adds the [`AsMut`] trait to a newtype type
macro_rules! generic_newtype_asmut {
    ($name:ident) => {
        impl<T> AsMut<$name<T>> for $name<T> {
            fn as_mut(&mut self) -> &mut $name<T> {
                self
            }
        }
    };
}

/// Adds the [`Deref`] trait to a newtype type that contains array data
macro_rules! generic_newtype_deref {
    ($name:ident, $n:expr) => {
        impl<T> Deref for $name<T> {
            type Target = [T; $n];
            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }
    };
}

/// Adds the [`DerefMut`] trait to a newtype type that contains array data
macro_rules! generic_newtype_deref_mut {
    ($name:ident) => {
        impl<T> DerefMut for $name<T> {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.0
            }
        }
    };
}

/// Adds the [`Index`] trait to a newtype type
macro_rules! generic_newtype_index {
    ($name:ident) => {
        impl<T, I> Index<I> for $name<T>
        where
            [T]: Index<I>,
        {
            type Output = <[T] as Index<I>>::Output;
            #[inline]
            fn index(&self, index: I) -> &Self::Output {
                Index::index(&self.0 as &[T], index)
            }
        }
    };
}

/// Adds the [`IndexMut`] trait to a newtype type
macro_rules! generic_newtype_index_mut {
    ($name:ident) => {
        impl<T, I> IndexMut<I> for $name<T>
        where
            [T]: IndexMut<I>,
        {
            #[inline]
            fn index_mut(&mut self, index: I) -> &mut Self::Output {
                IndexMut::index_mut(&mut self.0 as &mut [T], index)
            }
        }
    };
}

/// Adds the [`IntoIterator`] trait to a newtype type
macro_rules! generic_newtype_into_iter {
    ($name:ident, $n:expr) => {
        impl<'a, T> IntoIterator for &'a $name<T> {
            type Item = &'a T;
            type IntoIter = std::slice::Iter<'a, T>;

            fn into_iter(self) -> Self::IntoIter {
                self.0.iter()
            }
        }
        impl<'a, T> IntoIterator for &'a mut $name<T> {
            type Item = &'a mut T;
            type IntoIter = std::slice::IterMut<'a, T>;

            fn into_iter(self) -> Self::IntoIter {
                self.0.iter_mut()
            }
        }
        impl<T> IntoIterator for $name<T> {
            type Item = T;
            type IntoIter = std::array::IntoIter<Self::Item, $n>;

            fn into_iter(self) -> Self::IntoIter {
                self.0.into_iter()
            }
        }
    };
}

pub(crate) use generic_newtype_asmut;
pub(crate) use generic_newtype_asref;
pub(crate) use generic_newtype_deref;
pub(crate) use generic_newtype_deref_mut;
pub(crate) use generic_newtype_id_lookups;
pub(crate) use generic_newtype_index;
pub(crate) use generic_newtype_index_mut;
pub(crate) use generic_newtype_into_iter;
pub(crate) use generic_newtype_unbox;
pub(crate) use method_id;
pub(crate) use method_id_mut;
pub(crate) use method_id_ref;