use core::borrow::Borrow;
use core::convert::TryFrom;
use core::{fmt, ops};
pub use into_iter::IntoIter;
use super::Signature;
use crate::Error;
pub(crate) const MAX_LEN: usize = 72;
#[derive(Copy, Clone)]
pub struct SerializedSignature {
data: [u8; MAX_LEN],
len: usize,
}
impl fmt::Debug for SerializedSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
}
impl fmt::Display for SerializedSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for v in self {
write!(f, "{:02x}", v)?;
}
Ok(())
}
}
impl PartialEq for SerializedSignature {
#[inline]
fn eq(&self, other: &SerializedSignature) -> bool { **self == **other }
}
impl PartialEq<[u8]> for SerializedSignature {
#[inline]
fn eq(&self, other: &[u8]) -> bool { **self == *other }
}
impl PartialEq<SerializedSignature> for [u8] {
#[inline]
fn eq(&self, other: &SerializedSignature) -> bool { *self == **other }
}
impl PartialOrd for SerializedSignature {
fn partial_cmp(&self, other: &SerializedSignature) -> Option<core::cmp::Ordering> {
Some((**self).cmp(&**other))
}
}
impl Ord for SerializedSignature {
fn cmp(&self, other: &SerializedSignature) -> core::cmp::Ordering { (**self).cmp(&**other) }
}
impl PartialOrd<[u8]> for SerializedSignature {
fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
(**self).partial_cmp(other)
}
}
impl PartialOrd<SerializedSignature> for [u8] {
fn partial_cmp(&self, other: &SerializedSignature) -> Option<core::cmp::Ordering> {
self.partial_cmp(&**other)
}
}
impl core::hash::Hash for SerializedSignature {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { (**self).hash(state) }
}
impl AsRef<[u8]> for SerializedSignature {
#[inline]
fn as_ref(&self) -> &[u8] { self }
}
impl Borrow<[u8]> for SerializedSignature {
#[inline]
fn borrow(&self) -> &[u8] { self }
}
impl ops::Deref for SerializedSignature {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] { &self.data[..self.len] }
}
impl Eq for SerializedSignature {}
impl IntoIterator for SerializedSignature {
type IntoIter = IntoIter;
type Item = u8;
#[inline]
fn into_iter(self) -> Self::IntoIter { IntoIter::new(self) }
}
impl<'a> IntoIterator for &'a SerializedSignature {
type IntoIter = core::slice::Iter<'a, u8>;
type Item = &'a u8;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl From<Signature> for SerializedSignature {
fn from(value: Signature) -> Self { Self::from_signature(&value) }
}
impl<'a> From<&'a Signature> for SerializedSignature {
fn from(value: &'a Signature) -> Self { Self::from_signature(value) }
}
impl TryFrom<SerializedSignature> for Signature {
type Error = Error;
fn try_from(value: SerializedSignature) -> Result<Self, Self::Error> { value.to_signature() }
}
impl<'a> TryFrom<&'a SerializedSignature> for Signature {
type Error = Error;
fn try_from(value: &'a SerializedSignature) -> Result<Self, Self::Error> {
value.to_signature()
}
}
impl SerializedSignature {
#[inline]
pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
SerializedSignature { data, len }
}
#[deprecated = "This always returns 72"]
#[inline]
pub fn capacity(&self) -> usize { self.data.len() }
#[inline]
pub fn len(&self) -> usize { self.len }
#[inline]
pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
#[inline]
pub fn to_signature(&self) -> Result<Signature, Error> { Signature::from_der(self) }
#[inline]
pub fn from_signature(sig: &Signature) -> SerializedSignature { sig.serialize_der() }
#[deprecated = "This always returns false"]
#[inline]
pub fn is_empty(&self) -> bool { self.len() == 0 }
}
mod into_iter {
use super::*;
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone)]
pub struct IntoIter {
signature: SerializedSignature,
pos: usize,
}
impl IntoIter {
#[inline]
pub(crate) fn new(signature: SerializedSignature) -> Self {
IntoIter {
signature,
pos: 0,
}
}
#[inline]
pub fn as_slice(&self) -> &[u8] { &self.signature[self.pos..] }
}
impl Iterator for IntoIter {
type Item = u8;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let byte = *self.signature.get(self.pos)?;
self.pos += 1;
Some(byte)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.signature.len() - self.pos;
(len, Some(len))
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if n >= self.len() {
self.pos = self.signature.len();
None
} else {
self.pos += n;
self.next()
}
}
}
impl ExactSizeIterator for IntoIter {}
impl core::iter::FusedIterator for IntoIter {}
impl DoubleEndedIterator for IntoIter {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.pos == self.signature.len() {
return None;
}
let new_len = self.signature.len() - 1;
let byte = self.signature[new_len];
self.signature.set_len_unchecked(new_len);
Some(byte)
}
}
}
#[cfg(test)]
mod tests {
use super::{SerializedSignature, MAX_LEN};
#[test]
fn iterator_ops_are_homomorphic() {
let mut fake_signature_data = [0; MAX_LEN];
for (i, byte) in fake_signature_data.iter_mut().enumerate() {
*byte = i as u8; }
let fake_signature = SerializedSignature { data: fake_signature_data, len: MAX_LEN };
let mut iter1 = fake_signature.into_iter();
let mut iter2 = fake_signature.iter();
while let (Some(a), Some(b)) = (iter1.next(), iter2.next()) {
assert_eq!(a, *b);
assert_eq!(iter1.size_hint(), iter2.size_hint());
assert_eq!(iter1.as_slice(), iter2.as_slice());
}
let mut iter1 = fake_signature.into_iter();
let mut iter2 = fake_signature.iter();
while let (Some(a), Some(b)) = (iter1.next_back(), iter2.next_back()) {
assert_eq!(a, *b);
assert_eq!(iter1.size_hint(), iter2.size_hint());
assert_eq!(iter1.as_slice(), iter2.as_slice());
}
}
}