use super::KeyFormat;
use core::convert::TryFrom;
use core::fmt;
#[derive(Copy, Clone)] pub struct SerializedPublicKey {
data: [u8; 65],
}
impl SerializedPublicKey {
#[inline]
pub(super) fn new(key: secp256k1::PublicKey, format: KeyFormat) -> Self {
let data = match format {
KeyFormat::Uncompressed => {
let data = key.serialize_uncompressed();
debug_assert_eq!(data[0], 4);
data
},
KeyFormat::Compressed => {
let serialized = key.serialize();
debug_assert!(serialized[0] == 2 || serialized[0] == 3, "unexpected value {:#04x} in the first byte, the value must be either 0x02 or 0x03", serialized[0]);
let mut data = [0u8; 65];
data[..33].copy_from_slice(&serialized);
data
},
};
SerializedPublicKey {
data,
}
}
#[inline]
pub fn len(&self) -> usize {
self.as_slice().len()
}
#[inline]
pub fn iter(&self) -> core::slice::Iter<'_, u8> {
self.as_slice().iter()
}
#[inline]
pub fn as_slice(&self) -> &[u8] {
debug_assert!(self.data[0] == 4 || self.data[0] == 2 || self.data[0] == 3);
&self.data[..(33 + (usize::from(self.data[0] & 0b100) * 8))]
}
#[inline]
pub fn as_ptr(&self) -> *const u8 {
self.as_slice().as_ptr()
}
}
impl core::ops::Deref for SerializedPublicKey {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl AsRef<[u8]> for SerializedPublicKey {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl core::borrow::Borrow<[u8]> for SerializedPublicKey {
#[inline]
fn borrow(&self) -> &[u8] {
self.as_slice()
}
}
impl<'a> IntoIterator for &'a SerializedPublicKey {
type IntoIter = core::slice::Iter<'a, u8>;
type Item = &'a u8;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for SerializedPublicKey {
type IntoIter = IntoIter;
type Item = u8;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
key: self,
pos: 0,
}
}
}
impl PartialEq for SerializedPublicKey {
#[inline]
fn eq(&self, other: &SerializedPublicKey) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Eq for SerializedPublicKey {
}
impl PartialOrd for SerializedPublicKey {
#[inline]
fn partial_cmp(&self, other: &SerializedPublicKey) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for SerializedPublicKey {
#[inline]
fn cmp(&self, other: &SerializedPublicKey) -> core::cmp::Ordering {
let left = self.as_slice();
let right = other.as_slice();
if left[0] == right[0] {
left[1..].cmp(&right[1..])
} else {
left[0].cmp(&right[0])
}
}
}
impl core::hash::Hash for SerializedPublicKey {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
<[u8] as core::hash::Hash>::hash(self.as_slice(), state)
}
}
impl fmt::Debug for SerializedPublicKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for b in self {
write!(f, "{:02x}", b)?;
}
Ok(())
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct IntoIter {
key: SerializedPublicKey,
pos: u8,
}
impl IntoIter {
#[inline]
pub fn as_slice(&self) -> &[u8] {
&self.key[self.pos()..]
}
fn pos(&self) -> usize {
self.pos.into()
}
}
impl Iterator for IntoIter {
type Item = u8;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let item = *self.key.get(self.pos())?;
self.pos += 1;
debug_assert!(self.pos() <= self.key.len());
Some(item)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.key.len() - self.pos();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn last(self) -> Option<Self::Item> {
if self.pos() < self.key.len() {
Some(self.key[self.key.len() - 1])
} else {
None
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let elem_pos = self.pos.saturating_add(u8::try_from(n).unwrap_or(255));
if usize::from(elem_pos) < self.key.len() {
self.pos = elem_pos + 1;
Some(self.key[usize::from(elem_pos)])
} else {
None
}
}
}
impl ExactSizeIterator for IntoIter {}
impl core::iter::FusedIterator for IntoIter {}
#[cfg(feature = "alloc")]
mod alloc_impls {
use alloc::borrow::Cow;
use alloc::vec::Vec;
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::sync::Arc;
use super::SerializedPublicKey;
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl From<SerializedPublicKey> for Vec<u8> {
#[inline]
fn from(value: SerializedPublicKey) -> Self {
value.to_vec()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl From<SerializedPublicKey> for Box<[u8]> {
#[inline]
fn from(value: SerializedPublicKey) -> Self {
value.as_slice().into()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl From<SerializedPublicKey> for Rc<[u8]> {
#[inline]
fn from(value: SerializedPublicKey) -> Self {
value.as_slice().into()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl From<SerializedPublicKey> for Arc<[u8]> {
#[inline]
fn from(value: SerializedPublicKey) -> Self {
value.as_slice().into()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<'a> From<SerializedPublicKey> for Cow<'a, [u8]> {
#[inline]
fn from(value: SerializedPublicKey) -> Self {
Cow::Owned(value.into())
}
}
}