feat(primitives): Enable serde of ledger structs (#169)
This commit is contained in:
parent
1f0eb3bfc0
commit
9845fc4040
22 changed files with 584 additions and 270 deletions
|
|
@ -2,10 +2,9 @@
|
|||
//!
|
||||
//! we expose two helper objects:
|
||||
//!
|
||||
//! * [`Hasher`] to help streaming objects or bytes into a hasher
|
||||
//! and computing a hash without allocating extra memory due to
|
||||
//! the required **CBOR** encoding for everything by the cardano
|
||||
//! protocol
|
||||
//! * [`Hasher`] to help streaming objects or bytes into a hasher and computing
|
||||
//! a hash without allocating extra memory due to the required **CBOR**
|
||||
//! encoding for everything by the cardano protocol
|
||||
//! * [`struct@Hash`] a conveniently strongly typed byte array
|
||||
//!
|
||||
//! The algorithm exposed here is `Blake2b`. We currently support two
|
||||
|
|
@ -30,5 +29,6 @@
|
|||
#[allow(clippy::module_inception)]
|
||||
mod hash;
|
||||
mod hasher;
|
||||
mod serde;
|
||||
|
||||
pub use self::{hash::Hash, hasher::Hasher};
|
||||
|
|
|
|||
97
pallas-crypto/src/hash/serde.rs
Normal file
97
pallas-crypto/src/hash/serde.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::de::{Error, Unexpected, Visitor};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use super::Hash;
|
||||
|
||||
impl<const BYTES: usize> Serialize for Hash<BYTES> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
struct HashVisitor<const BYTES: usize> {}
|
||||
|
||||
impl<'de, const BYTES: usize> Visitor<'de> for HashVisitor<BYTES> {
|
||||
type Value = Hash<BYTES>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "a hex string representing {} bytes", BYTES)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match Hash::<BYTES>::from_str(s) {
|
||||
Ok(x) => Ok(x),
|
||||
Err(_) => Err(Error::invalid_value(Unexpected::Str(s), &self)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, const BYTES: usize> Deserialize<'de> for Hash<BYTES> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_str(HashVisitor::<BYTES> {})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_test::{assert_de_tokens_error, assert_tokens, Token};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
struct Dummy {
|
||||
hash1: Hash<28>,
|
||||
hash2: Hash<32>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn output_tokens() {
|
||||
let dummy = Dummy {
|
||||
hash1: "276fd18711931e2c0e21430192dbeac0e458093cd9d1fcd7210f64b3"
|
||||
.parse()
|
||||
.unwrap(),
|
||||
hash2: "0d8d00cdd4657ac84d82f0a56067634a7adfdf43da41cb534bcaa45060973d21"
|
||||
.parse()
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&dummy,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Dummy",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("hash1"),
|
||||
Token::Str("276fd18711931e2c0e21430192dbeac0e458093cd9d1fcd7210f64b3"),
|
||||
Token::Str("hash2"),
|
||||
Token::Str("0d8d00cdd4657ac84d82f0a56067634a7adfdf43da41cb534bcaa45060973d21"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_str() {
|
||||
assert_de_tokens_error::<Dummy>(
|
||||
&[
|
||||
Token::Map { len: Some(2) },
|
||||
Token::Str("hash1"),
|
||||
Token::Str("27"),
|
||||
],
|
||||
"invalid value: string \"27\", expected a hex string representing 28 bytes",
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue