#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype {
($outer:ident, $inner: ty) => {
impl From<$inner> for $outer {
fn from(inner: $inner) -> Self {
$outer(inner)
}
}
impl<R: ?Sized> AsRef<R> for $outer
where
$inner: AsRef<R>,
{
fn as_ref(&self) -> &R {
self.0.as_ref()
}
}
impl<R: ?Sized> AsMut<R> for $outer
where
$inner: AsMut<R>,
{
fn as_mut(&mut self) -> &mut R {
self.0.as_mut()
}
}
impl ::std::ops::Deref for $outer {
type Target = $inner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ::std::ops::DerefMut for $outer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl ::std::borrow::Borrow<$inner> for $outer {
fn borrow(&self) -> &$inner {
&self.0
}
}
impl ::std::borrow::BorrowMut<$inner> for $outer {
fn borrow_mut(&mut self) -> &mut $inner {
&mut self.0
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_old {
($outer: ident, $inner: ty) => {
impl ::std::ops::Deref for $outer {
type Target = $inner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ::std::ops::DerefMut for $outer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl ::std::convert::From<$inner> for $outer {
fn from(inner: $inner) -> Self {
$outer(inner)
}
}
impl AsRef<$inner> for $outer {
fn as_ref(&self) -> &$inner {
&self.0
}
}
impl AsMut<$inner> for $outer {
fn as_mut(&mut self) -> &mut $inner {
&mut self.0
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_array {
($outer: ident, $inner: ty, $len: expr) => {
impl_newtype!($outer, [u8; $len]);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_hexfmt {
($outer: ident, $lowtoken: expr, $uptoken: expr) => {
impl ::std::fmt::LowerHex for $outer {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let bytes: &[u8] = self.as_ref();
for val in bytes.iter() {
write!(f, $lowtoken, val)?;
}
Ok(())
}
}
impl ::std::fmt::UpperHex for $outer {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let bytes: &[u8] = self.as_ref();
for val in bytes.iter() {
write!(f, $uptoken, val)?;
}
Ok(())
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_bytearray {
($outer: ident, $len: expr) => {
impl_newtype_array!($outer, u8, $len);
impl_newtype_hexfmt!($outer, "{:02x}", "{:02X}");
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_array_ext {
($outer: ident, $inner: ty, $len:expr) => {
impl_newtype_array!($outer, $inner, $len);
impl ::std::cmp::PartialEq for $outer {
fn eq(&self, other: &$outer) -> bool {
let sref: &[$inner] = self.as_ref();
let oref: &[$inner] = other.as_ref();
sref == oref
}
}
impl ::std::cmp::Eq for $outer {}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_numarray_ext {
($outer: ident, $inner: ty, $len:expr) => {
impl Clone for $outer {
fn clone(&self) -> Self {
let mut buf = [<$inner as Default>::default(); $len];
let s: &[$inner] = self.as_ref();
for (idx, itm) in s.iter().enumerate() {
buf[idx] = *itm;
}
buf.into()
}
}
impl Default for $outer {
fn default() -> Self {
$outer([<$inner as Default>::default(); $len])
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_newtype_bytearray_ext {
($outer: ident, $len:expr) => {
impl_newtype_array_ext!($outer, u8, $len);
impl_newtype_hexfmt!($outer, "{:02x}", "{:02X}");
impl_newtype_numarray_ext!($outer, u8, $len);
};
}
#[cfg(test)]
mod tests {
#[test]
fn implementation() {
struct Bar([u8; 36]);
impl_newtype_bytearray_ext!(Bar, 36);
}
}