1use core::fmt;
8
9use crate::prelude::*;
10use crate::serialize::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct DleqProof(pub [u8; 64]);
15
16#[cfg(feature = "serde")]
17impl serde::Serialize for DleqProof {
18 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
19 where
20 S: serde::Serializer,
21 {
22 if serializer.is_human_readable() {
23 serializer.serialize_str(&bitcoin::hex::DisplayHex::to_lower_hex_string(&self.0[..]))
24 } else {
25 serializer.serialize_bytes(&self.0[..])
26 }
27 }
28}
29
30#[cfg(feature = "serde")]
31impl<'de> serde::Deserialize<'de> for DleqProof {
32 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33 where
34 D: serde::Deserializer<'de>,
35 {
36 if deserializer.is_human_readable() {
37 struct HexVisitor;
38 impl serde::de::Visitor<'_> for HexVisitor {
39 type Value = DleqProof;
40
41 fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
42 f.write_str("a 64-byte hex string")
43 }
44
45 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
46 where
47 E: serde::de::Error,
48 {
49 use bitcoin::hex::FromHex;
50 let vec = Vec::<u8>::from_hex(s).map_err(E::custom)?;
51 DleqProof::try_from(vec).map_err(|e| {
52 E::custom(format!("expected {} bytes, got {}", e.expected, e.got))
53 })
54 }
55 }
56 deserializer.deserialize_str(HexVisitor)
57 } else {
58 struct BytesVisitor;
59 impl serde::de::Visitor<'_> for BytesVisitor {
60 type Value = DleqProof;
61
62 fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
63 f.write_str("64 bytes")
64 }
65
66 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
67 where
68 E: serde::de::Error,
69 {
70 DleqProof::try_from(v).map_err(|e| {
71 E::custom(format!("expected {} bytes, got {}", e.expected, e.got))
72 })
73 }
74 }
75 deserializer.deserialize_bytes(BytesVisitor)
76 }
77 }
78}
79
80impl DleqProof {
81 pub fn as_bytes(&self) -> &[u8; 64] { &self.0 }
83}
84
85impl From<[u8; 64]> for DleqProof {
86 fn from(bytes: [u8; 64]) -> Self { DleqProof(bytes) }
87}
88
89impl AsRef<[u8]> for DleqProof {
90 fn as_ref(&self) -> &[u8] { &self.0 }
91}
92
93impl TryFrom<&[u8]> for DleqProof {
94 type Error = InvalidLengthError;
95
96 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
97 <[u8; 64]>::try_from(slice)
98 .map(DleqProof)
99 .map_err(|_| InvalidLengthError { got: slice.len(), expected: 64 })
100 }
101}
102
103impl TryFrom<Vec<u8>> for DleqProof {
104 type Error = InvalidLengthError;
105
106 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> { Self::try_from(v.as_slice()) }
107}
108
109impl Serialize for DleqProof {
110 fn serialize(&self) -> Vec<u8> { self.0.to_vec() }
111}
112
113impl Deserialize for DleqProof {
114 fn deserialize(bytes: &[u8]) -> Result<Self, crate::serialize::Error> {
115 DleqProof::try_from(bytes).map_err(|e| {
116 crate::serialize::Error::InvalidDleqProof(InvalidLengthError {
117 got: e.got,
118 expected: e.expected,
119 })
120 })
121 }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub struct InvalidLengthError {
127 pub got: usize,
129 pub expected: usize,
131}
132
133impl fmt::Display for InvalidLengthError {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 write!(f, "invalid length for BIP-375 type: got {}, expected {}", self.got, self.expected)
136 }
137}
138
139#[cfg(feature = "std")]
140impl std::error::Error for InvalidLengthError {}