use core::fmt;
use crate::prelude::*;
use crate::serialize::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DleqProof(pub [u8; 64]);
#[cfg(feature = "serde")]
impl serde::Serialize for DleqProof {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
if serializer.is_human_readable() {
serializer.serialize_str(&bitcoin::hex::DisplayHex::to_lower_hex_string(&self.0[..]))
} else {
serializer.serialize_bytes(&self.0[..])
}
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for DleqProof {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
if deserializer.is_human_readable() {
struct HexVisitor;
impl serde::de::Visitor<'_> for HexVisitor {
type Value = DleqProof;
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str("a 64-byte hex string")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
use bitcoin::hex::FromHex;
let vec = Vec::<u8>::from_hex(s).map_err(E::custom)?;
DleqProof::try_from(vec).map_err(|e| {
E::custom(format!("expected {} bytes, got {}", e.expected, e.got))
})
}
}
deserializer.deserialize_str(HexVisitor)
} else {
struct BytesVisitor;
impl serde::de::Visitor<'_> for BytesVisitor {
type Value = DleqProof;
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str("64 bytes")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
DleqProof::try_from(v).map_err(|e| {
E::custom(format!("expected {} bytes, got {}", e.expected, e.got))
})
}
}
deserializer.deserialize_bytes(BytesVisitor)
}
}
}
impl DleqProof {
pub fn as_bytes(&self) -> &[u8; 64] { &self.0 }
}
impl From<[u8; 64]> for DleqProof {
fn from(bytes: [u8; 64]) -> Self { DleqProof(bytes) }
}
impl AsRef<[u8]> for DleqProof {
fn as_ref(&self) -> &[u8] { &self.0 }
}
impl TryFrom<&[u8]> for DleqProof {
type Error = InvalidLengthError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
<[u8; 64]>::try_from(slice)
.map(DleqProof)
.map_err(|_| InvalidLengthError { got: slice.len(), expected: 64 })
}
}
impl TryFrom<Vec<u8>> for DleqProof {
type Error = InvalidLengthError;
fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> { Self::try_from(v.as_slice()) }
}
impl Serialize for DleqProof {
fn serialize(&self) -> Vec<u8> { self.0.to_vec() }
}
impl Deserialize for DleqProof {
fn deserialize(bytes: &[u8]) -> Result<Self, crate::serialize::Error> {
DleqProof::try_from(bytes).map_err(|e| {
crate::serialize::Error::InvalidDleqProof(InvalidLengthError {
got: e.got,
expected: e.expected,
})
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InvalidLengthError {
pub got: usize,
pub expected: usize,
}
impl fmt::Display for InvalidLengthError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "invalid length for BIP-375 type: got {}, expected {}", self.got, self.expected)
}
}
#[cfg(feature = "std")]
impl std::error::Error for InvalidLengthError {}