use crate::{Error, Event};
use derive_more::{AsMut, AsRef, Deref, Display, From, FromStr, Into};
use k256::schnorr::Signature as KSignature;
use serde::de::Error as DeserializeError;
use serde::de::{Deserialize as De, Deserializer, Visitor};
use serde::ser::{Serialize as Se, Serializer};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(AsMut, AsRef, Clone, Copy, Debug, Deref, Eq, From, Into, PartialEq)]
pub struct Signature(pub KSignature);
impl Signature {
pub fn as_hex_string(&self) -> String {
hex::encode(self.0.to_bytes())
}
pub fn try_from_hex_string(v: &str) -> Result<Signature, Error> {
let vec: Vec<u8> = hex::decode(v)?;
Ok(Signature(KSignature::try_from(&*vec)?))
}
#[allow(dead_code)]
pub(crate) fn mock() -> Signature {
let event = Event::mock();
event.sig
}
}
impl Se for Signature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&hex::encode(self.to_bytes()))
}
}
impl<'de> De<'de> for Signature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(SignatureVisitor)
}
}
struct SignatureVisitor;
impl Visitor<'_> for SignatureVisitor {
type Value = Signature;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a hexadecimal string representing 64 bytes")
}
fn visit_str<E>(self, v: &str) -> Result<Signature, E>
where
E: serde::de::Error,
{
let vec: Vec<u8> =
hex::decode(v).map_err(|e| serde::de::Error::custom(format!("{}", e)))?;
if vec.len() != 64 {
return Err(serde::de::Error::custom("Signature is not 64 bytes long"));
}
let ksig: KSignature =
KSignature::try_from(&*vec).map_err(|e| DeserializeError::custom(format!("{}", e)))?;
Ok(Signature(ksig))
}
}
#[derive(
AsMut,
AsRef,
Clone,
Debug,
Deref,
Deserialize,
Display,
Eq,
From,
FromStr,
Hash,
Into,
PartialEq,
Serialize,
)]
pub struct SignatureHex(pub String);
impl SignatureHex {
#[allow(dead_code)]
pub(crate) fn mock() -> SignatureHex {
From::from(Signature::mock())
}
}
impl From<Signature> for SignatureHex {
fn from(s: Signature) -> SignatureHex {
SignatureHex(s.as_hex_string())
}
}
impl TryFrom<SignatureHex> for Signature {
type Error = Error;
fn try_from(sh: SignatureHex) -> Result<Signature, Error> {
Signature::try_from_hex_string(&sh.0)
}
}
#[cfg(test)]
mod test {
use super::*;
test_serde! {Signature, test_signature_serde}
}