Skip to content

Commit e6d304f

Browse files
committed
graph: implement deserialize for BlockPtrExt and add tests
1 parent 2063909 commit e6d304f

File tree

1 file changed

+90
-2
lines changed

1 file changed

+90
-2
lines changed

graph/src/blockchain/types.rs

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use diesel::serialize::{Output, ToSql};
55
use diesel::sql_types::Timestamptz;
66
use diesel::sql_types::{Bytea, Nullable, Text};
77
use diesel_derives::{AsExpression, FromSqlRow};
8-
use serde::Deserialize;
8+
use serde::{Deserialize, Deserializer};
99
use std::convert::TryFrom;
1010
use std::time::Duration;
1111
use std::{fmt, str::FromStr};
@@ -21,7 +21,7 @@ use crate::prelude::{r, BigInt, TryFromValue, Value, ValueMap};
2121
use crate::util::stable_hash_glue::{impl_stable_hash, AsBytes};
2222

2323
/// A simple marker for byte arrays that are really block hashes
24-
#[derive(Clone, Default, PartialEq, Eq, Hash, FromSqlRow, AsExpression, Deserialize)]
24+
#[derive(Clone, Default, PartialEq, Eq, Hash, FromSqlRow, AsExpression)]
2525
#[diesel(sql_type = Bytea)]
2626
pub struct BlockHash(pub Box<[u8]>);
2727

@@ -49,6 +49,16 @@ impl BlockHash {
4949
}
5050
}
5151

52+
impl<'de> Deserialize<'de> for BlockHash {
53+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
54+
where
55+
D: Deserializer<'de>,
56+
{
57+
let s: String = Deserialize::deserialize(deserializer)?;
58+
BlockHash::from_str(&s).map_err(serde::de::Error::custom)
59+
}
60+
}
61+
5262
impl CheapClone for BlockHash {
5363
fn cheap_clone(&self) -> Self {
5464
Self(self.0.clone())
@@ -331,9 +341,25 @@ impl From<BlockPtr> for BlockNumber {
331341
}
332342
}
333343

344+
fn deserialize_block_number<'de, D>(deserializer: D) -> Result<BlockNumber, D::Error>
345+
where
346+
D: Deserializer<'de>,
347+
{
348+
let s: String = Deserialize::deserialize(deserializer)?;
349+
350+
if s.starts_with("0x") {
351+
let s = s.trim_start_matches("0x");
352+
i32::from_str_radix(s, 16).map_err(serde::de::Error::custom)
353+
} else {
354+
i32::from_str(&s).map_err(serde::de::Error::custom)
355+
}
356+
}
357+
334358
#[derive(Clone, PartialEq, Eq, Hash, Deserialize)]
359+
#[serde(rename_all = "camelCase")]
335360
pub struct BlockPtrExt {
336361
pub hash: BlockHash,
362+
#[serde(deserialize_with = "deserialize_block_number")]
337363
pub number: BlockNumber,
338364
pub parent_hash: BlockHash,
339365
pub timestamp: U256,
@@ -577,3 +603,65 @@ impl ToSql<Timestamptz, Pg> for BlockTime {
577603
<Timestamp as ToSql<Timestamptz, Pg>>::to_sql(&self.0, out)
578604
}
579605
}
606+
607+
#[cfg(test)]
608+
mod tests {
609+
use super::*;
610+
use serde_json;
611+
612+
#[test]
613+
fn test_blockhash_deserialization() {
614+
let json_data = "\"0x8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac\"";
615+
616+
let block_hash: BlockHash =
617+
serde_json::from_str(json_data).expect("Deserialization failed");
618+
619+
let expected_bytes =
620+
hex::decode("8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac")
621+
.expect("Hex decoding failed");
622+
623+
assert_eq!(
624+
*block_hash.0, expected_bytes,
625+
"BlockHash does not match expected bytes"
626+
);
627+
}
628+
629+
#[test]
630+
fn test_block_ptr_ext_deserialization() {
631+
// JSON data with a hex string for BlockNumber
632+
let json_data = r#"
633+
{
634+
"hash": "0x8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac",
635+
"number": "0x2A",
636+
"parentHash": "0xabc123",
637+
"timestamp": "123456789012345678901234567890"
638+
}
639+
"#;
640+
641+
// Deserialize the JSON string into a BlockPtrExt
642+
let block_ptr_ext: BlockPtrExt =
643+
serde_json::from_str(json_data).expect("Deserialization failed");
644+
645+
// Verify the deserialized values
646+
assert_eq!(block_ptr_ext.number, 42); // 0x2A in hex is 42 in decimal
647+
}
648+
649+
#[test]
650+
fn test_invalid_block_number_deserialization() {
651+
let invalid_json_data = r#"
652+
{
653+
"hash": "0x8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac",
654+
"number": "invalid_hex_string",
655+
"parentHash": "0xabc123",
656+
"timestamp": "123456789012345678901234567890"
657+
}
658+
"#;
659+
660+
let result: Result<BlockPtrExt, _> = serde_json::from_str(invalid_json_data);
661+
662+
assert!(
663+
result.is_err(),
664+
"Deserialization should have failed for invalid block number"
665+
);
666+
}
667+
}

0 commit comments

Comments
 (0)