1use alloc::boxed::Box;
4use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex};
5use crypto_bigint::BoxedUint;
6use signature::SignatureEncoding;
7
8#[cfg(feature = "serde")]
9use serdect::serde::{de, Deserialize, Serialize};
10#[cfg(feature = "encoding")]
11use spki::{
12 der::{asn1::BitString, Result as DerResult},
13 SignatureBitStringEncoding,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct Signature {
21 pub(super) inner: BoxedUint,
22}
23
24impl SignatureEncoding for Signature {
25 type Repr = Box<[u8]>;
26}
27
28#[cfg(feature = "encoding")]
29impl SignatureBitStringEncoding for Signature {
30 fn to_bitstring(&self) -> DerResult<BitString> {
31 BitString::new(0, self.to_vec())
32 }
33}
34
35impl TryFrom<&[u8]> for Signature {
36 type Error = signature::Error;
37
38 fn try_from(bytes: &[u8]) -> signature::Result<Self> {
39 let inner = BoxedUint::from_be_slice_vartime(bytes);
41 Ok(Self { inner })
42 }
43}
44
45impl From<Signature> for Box<[u8]> {
46 fn from(signature: Signature) -> Box<[u8]> {
47 signature.inner.to_be_bytes()
48 }
49}
50
51impl LowerHex for Signature {
52 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
53 write!(f, "{:x}", &self.inner)
54 }
55}
56
57impl UpperHex for Signature {
58 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
59 write!(f, "{:X}", &self.inner)
60 }
61}
62
63impl Display for Signature {
64 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
65 write!(f, "{:X}", self)
66 }
67}
68
69#[cfg(feature = "serde")]
70impl Serialize for Signature {
71 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
72 where
73 S: serdect::serde::Serializer,
74 {
75 serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer)
76 }
77}
78
79#[cfg(feature = "serde")]
80impl<'de> Deserialize<'de> for Signature {
81 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
82 where
83 D: serdect::serde::Deserializer<'de>,
84 {
85 serdect::slice::deserialize_hex_or_bin_vec(deserializer)?
86 .as_slice()
87 .try_into()
88 .map_err(de::Error::custom)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 #[test]
95 #[cfg(feature = "serde")]
96 fn test_serde() {
97 use super::*;
98 use serde_test::{assert_tokens, Configure, Token};
99 let signature = Signature {
100 inner: BoxedUint::from(42u32),
101 };
102
103 let tokens = [Token::Str("000000000000002a")];
104 assert_tokens(&signature.readable(), &tokens);
105 }
106}