macro_rules! newtype_clone (($newtype:ident) => (
impl Clone for $newtype {
fn clone(&self) -> $newtype {
let &$newtype(v) = self;
$newtype(v)
}
}
));
macro_rules! newtype_from_slice (($newtype:ident, $len:expr) => (
pub fn from_slice(bs: &[u8]) -> Option<$newtype> {
if bs.len() != $len {
return None;
}
let mut n = $newtype([0; $len]);
{
let $newtype(ref mut b) = n;
for (bi, &bsi) in b.iter_mut().zip(bs.iter()) {
*bi = bsi
}
}
Some(n)
}
));
macro_rules! newtype_traits (($newtype:ident, $len:expr) => (
impl ::std::cmp::PartialEq for $newtype {
fn eq(&self, &$newtype(ref other): &$newtype) -> bool {
use shared::memcmp;
let &$newtype(ref this) = self;
memcmp(this, other)
}
}
impl ::std::cmp::Eq for $newtype {}
impl ::serde::Serialize for $newtype {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer {
serializer.serialize_bytes(&self[..])
}
}
impl ::serde::Deserialize for $newtype {
fn deserialize<D>(deserializer: D) -> Result<$newtype, D::Error> where D: ::serde::Deserializer {
struct NewtypeVisitor;
impl ::serde::de::Visitor for NewtypeVisitor {
type Value = $newtype;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(formatter, stringify!($newtype))
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> where V: ::serde::de::SeqVisitor {
let mut res = $newtype([0; $len]);
{
let $newtype(ref mut arr) = res;
for r in arr.iter_mut() {
if let Some(value) = try!(visitor.visit()) {
*r = value;
}
}
}
Ok(res)
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> where E: ::serde::de::Error {
$newtype::from_slice(v).ok_or(::serde::de::Error::invalid_length(v.len(), &self))
}
}
deserializer.deserialize_bytes(NewtypeVisitor)
}
}
impl ::std::ops::Index<::std::ops::Range<usize>> for $newtype {
type Output = [u8];
fn index(&self, _index: ::std::ops::Range<usize>) -> &[u8] {
let &$newtype(ref b) = self;
b.index(_index)
}
}
impl ::std::ops::Index<::std::ops::RangeTo<usize>> for $newtype {
type Output = [u8];
fn index(&self, _index: ::std::ops::RangeTo<usize>) -> &[u8] {
let &$newtype(ref b) = self;
b.index(_index)
}
}
impl ::std::ops::Index<::std::ops::RangeFrom<usize>> for $newtype {
type Output = [u8];
fn index(&self, _index: ::std::ops::RangeFrom<usize>) -> &[u8] {
let &$newtype(ref b) = self;
b.index(_index)
}
}
impl ::std::ops::Index<::std::ops::RangeFull> for $newtype {
type Output = [u8];
fn index(&self, _index: ::std::ops::RangeFull) -> &[u8] {
let &$newtype(ref b) = self;
b.index(_index)
}
}
impl ::std::fmt::Debug for $newtype {
fn fmt(&self,
formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(formatter, "{}({:?})", stringify!($newtype), &self[..])
}
}
));
macro_rules! public_newtype_traits (($newtype:ident) => (
impl AsRef<[u8]> for $newtype {
#[inline]
fn as_ref(&self) -> &[u8] {
&self[..]
}
}
impl ::std::cmp::PartialOrd for $newtype {
#[inline]
fn partial_cmp(&self,
other: &$newtype) -> Option<::std::cmp::Ordering> {
::std::cmp::PartialOrd::partial_cmp(self.as_ref(), other.as_ref())
}
#[inline]
fn lt(&self, other: &$newtype) -> bool {
::std::cmp::PartialOrd::lt(self.as_ref(), other.as_ref())
}
#[inline]
fn le(&self, other: &$newtype) -> bool {
::std::cmp::PartialOrd::le(self.as_ref(), other.as_ref())
}
#[inline]
fn ge(&self, other: &$newtype) -> bool {
::std::cmp::PartialOrd::ge(self.as_ref(), other.as_ref())
}
#[inline]
fn gt(&self, other: &$newtype) -> bool {
::std::cmp::PartialOrd::gt(self.as_ref(), other.as_ref())
}
}
impl ::std::cmp::Ord for $newtype {
#[inline]
fn cmp(&self, other: &$newtype) -> ::std::cmp::Ordering {
::std::cmp::Ord::cmp(self.as_ref(), other.as_ref())
}
}
impl ::std::hash::Hash for $newtype {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
::std::hash::Hash::hash(self.as_ref(), state)
}
}
));
macro_rules! new_type {
( $(#[$meta:meta])*
secret $name:ident($bytes:expr);
) => (
$(#[$meta])*
#[must_use]
pub struct $name(pub [u8; $bytes]);
newtype_clone!($name);
newtype_traits!($name, $bytes);
impl $name {
newtype_from_slice!($name, $bytes);
}
impl Drop for $name {
fn drop(&mut self) {
use shared::memzero;
let &mut $name(ref mut v) = self;
memzero(v);
println!("Dropping Secret KEY, Memory has been zeroed!!!!!");
}
}
);
( $(#[$meta:meta])*
public $name:ident($bytes:expr);
) => (
$(#[$meta])*
#[derive(Copy)]
#[must_use]
pub struct $name(pub [u8; $bytes]);
newtype_clone!($name);
newtype_traits!($name, $bytes);
public_newtype_traits!($name);
impl $name {
newtype_from_slice!($name, $bytes);
}
);
( $(#[$meta:meta])*
nonce $name:ident($bytes:expr);
) => (
$(#[$meta])*
#[derive(Copy)]
#[must_use]
pub struct $name(pub [u8; $bytes]);
newtype_clone!($name);
newtype_traits!($name, $bytes);
public_newtype_traits!($name);
impl $name {
newtype_from_slice!($name, $bytes);
}
);
}