essential_types/serde/
signature.rs

1//! Helpers for serializing and deserializing `Signature` types.
2//!
3//! Serializes the signature as a sequence of 65 bytes (64 for the signature, 1 for the ID).
4//!
5//! Human readable serialization formats are serialized as a 65-byte, upper hex string.
6
7pub use super::hash::{deserialize, serialize};
8use crate::Signature;
9use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
10
11impl Serialize for Signature {
12    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13    where
14        S: Serializer,
15    {
16        if serializer.is_human_readable() {
17            let bytes: [u8; 65] = self.clone().into();
18            let string = hex::encode_upper(bytes);
19            string.serialize(serializer)
20        } else {
21            let mut seq = serializer.serialize_seq(Some(self.0.len() + 1))?;
22            for b in &self.0 {
23                seq.serialize_element(b)?;
24            }
25            seq.serialize_element(&self.1)?;
26            seq.end()
27        }
28    }
29}
30
31impl<'de> Deserialize<'de> for Signature {
32    fn deserialize<D>(d: D) -> Result<Self, D::Error>
33    where
34        D: Deserializer<'de>,
35    {
36        let bytes: [u8; 65] = crate::serde::hash::deserialize(d)?;
37        Ok(bytes.into())
38    }
39}
40
41#[cfg(feature = "schema")]
42/// Custom JSON schema for `crate::Signature` due to no derive for [u8; 64].
43impl schemars::JsonSchema for crate::Signature {
44    fn schema_name() -> String {
45        "Signature".to_string()
46    }
47
48    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
49        let sig_arr = schemars::schema::SchemaObject {
50            metadata: Some(Box::new(schemars::schema::Metadata {
51                description: Some("Compact signature".to_string()),
52                ..Default::default()
53            })),
54            instance_type: Some(schemars::schema::InstanceType::Array.into()),
55            array: Some(Box::new(schemars::schema::ArrayValidation {
56                items: Some(gen.subschema_for::<u8>().into()),
57                max_items: Some(64),
58                min_items: Some(64),
59                ..Default::default()
60            })),
61            ..Default::default()
62        };
63        let mut data = schemars::schema::SchemaObject {
64            metadata: Some(Box::new(schemars::schema::Metadata {
65                description: Some("Recoverable ECDSA signature over some data.".to_string()),
66                ..Default::default()
67            })),
68            instance_type: Some(schemars::schema::InstanceType::Array.into()),
69            ..Default::default()
70        };
71        let mut id = gen.subschema_for::<u8>().into_object();
72        id.metadata = Some(Box::new(schemars::schema::Metadata {
73            description: Some("ID used for public key recovery".to_string()),
74            ..Default::default()
75        }));
76        let arr = data.array();
77        arr.items = Some(vec![sig_arr.into(), id.into()].into());
78        arr.max_items = Some(2);
79        arr.min_items = Some(2);
80        data.into()
81    }
82
83    fn is_referenceable() -> bool {
84        true
85    }
86
87    fn schema_id() -> std::borrow::Cow<'static, str> {
88        std::borrow::Cow::Owned(Self::schema_name())
89    }
90}