1use std::fmt;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _};
4
5use crate::base58::DecodeBase58Error;
6
7pub const SIGNATURE_BYTES: usize = 64;
9
10#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
12pub struct SignatureBytes([u8; SIGNATURE_BYTES]);
13
14impl SignatureBytes {
15 #[must_use]
17 pub const fn new(bytes: [u8; SIGNATURE_BYTES]) -> Self {
18 Self(bytes)
19 }
20
21 #[must_use]
23 pub const fn into_array(self) -> [u8; SIGNATURE_BYTES] {
24 self.0
25 }
26
27 #[must_use]
29 pub const fn as_array(&self) -> &[u8; SIGNATURE_BYTES] {
30 &self.0
31 }
32
33 pub fn from_base58(value: &str) -> Result<Self, DecodeBase58Error> {
39 let decoded =
40 bs58::decode(value)
41 .into_vec()
42 .map_err(|error| DecodeBase58Error::InvalidBase58 {
43 message: error.to_string(),
44 })?;
45 let bytes: [u8; SIGNATURE_BYTES] =
46 decoded
47 .try_into()
48 .map_err(|decoded: Vec<u8>| DecodeBase58Error::WrongLength {
49 expected: SIGNATURE_BYTES,
50 actual: decoded.len(),
51 })?;
52 Ok(Self(bytes))
53 }
54
55 #[must_use]
57 pub fn to_base58(self) -> String {
58 bs58::encode(self.0).into_string()
59 }
60}
61
62impl From<[u8; SIGNATURE_BYTES]> for SignatureBytes {
63 fn from(value: [u8; SIGNATURE_BYTES]) -> Self {
64 Self::new(value)
65 }
66}
67
68impl From<SignatureBytes> for [u8; SIGNATURE_BYTES] {
69 fn from(value: SignatureBytes) -> Self {
70 value.into_array()
71 }
72}
73
74impl fmt::Display for SignatureBytes {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 f.write_str(&self.to_base58())
77 }
78}
79
80impl Serialize for SignatureBytes {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: Serializer,
84 {
85 serializer.serialize_bytes(&self.0)
86 }
87}
88
89impl<'de> Deserialize<'de> for SignatureBytes {
90 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91 where
92 D: Deserializer<'de>,
93 {
94 let bytes = Vec::<u8>::deserialize(deserializer)?;
95 let signature: [u8; SIGNATURE_BYTES] = bytes
96 .try_into()
97 .map_err(|bytes: Vec<u8>| D::Error::invalid_length(bytes.len(), &"64 bytes"))?;
98 Ok(Self::new(signature))
99 }
100}
101
102#[cfg(feature = "solana-compat")]
103impl SignatureBytes {
104 #[must_use]
106 pub fn from_solana(value: solana_signature::Signature) -> Self {
107 Self::new(value.into())
108 }
109
110 #[must_use]
112 pub fn to_solana(self) -> solana_signature::Signature {
113 solana_signature::Signature::from(self.into_array())
114 }
115}
116
117#[cfg(feature = "solana-compat")]
118impl From<solana_signature::Signature> for SignatureBytes {
119 fn from(value: solana_signature::Signature) -> Self {
120 Self::from_solana(value)
121 }
122}
123
124#[cfg(feature = "solana-compat")]
125impl From<SignatureBytes> for solana_signature::Signature {
126 fn from(value: SignatureBytes) -> Self {
127 value.to_solana()
128 }
129}