mithril_persistence/database/
hydrator.rs1use serde::Deserialize;
4
5use mithril_common::entities::{
6 BlockNumber, CardanoDbBeacon, Epoch, SignedEntityType, SignedEntityTypeDiscriminants,
7};
8
9use crate::sqlite::HydrationError;
10
11pub struct Hydrator;
13
14impl Hydrator {
15 pub fn read_signed_entity_beacon_column<U: sqlite::RowIndex + Clone>(
17 row: &sqlite::Row,
18 column_index: U,
19 ) -> String {
20 match row.try_read::<&str, _>(column_index.clone()) {
25 Ok(value) => value.to_string(),
26 Err(_) => (row.read::<i64, _>(column_index)).to_string(),
27 }
28 }
29
30 pub fn try_to_u64(field: &str, value: i64) -> Result<u64, HydrationError> {
32 u64::try_from(value)
33 .map_err(|e|
34 HydrationError::InvalidData(
35 format!("Integer field {field} (value={value}) is incompatible with u64 representation. Error = {e}")
36 )
37 )
38 }
39
40 pub fn hydrate_signed_entity_type(
42 signed_entity_type_id: usize,
43 beacon_str: &str,
44 ) -> Result<SignedEntityType, HydrationError> {
45 let signed_entity = match SignedEntityTypeDiscriminants::from_id(signed_entity_type_id)
46 .map_err(|e| {
47 HydrationError::InvalidData(format!("Unknown signed entity. Error: {e}."))
48 })? {
49 SignedEntityTypeDiscriminants::MithrilStakeDistribution => {
50 let epoch: Epoch = serde_json::from_str(beacon_str).map_err(|e| {
51 HydrationError::InvalidData(format!(
52 "Invalid Epoch JSON representation '{beacon_str}. Error: {e}'."
53 ))
54 })?;
55 SignedEntityType::MithrilStakeDistribution(epoch)
56 }
57 SignedEntityTypeDiscriminants::CardanoStakeDistribution => {
58 let epoch: Epoch = serde_json::from_str(beacon_str).map_err(|e| {
59 HydrationError::InvalidData(format!(
60 "Invalid Epoch JSON representation '{beacon_str}. Error: {e}'."
61 ))
62 })?;
63 SignedEntityType::CardanoStakeDistribution(epoch)
64 }
65 SignedEntityTypeDiscriminants::CardanoImmutableFilesFull => {
66 let beacon: CardanoDbBeacon = serde_json::from_str(beacon_str).map_err(|e| {
67 HydrationError::InvalidData(format!(
68 "Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
69 ))
70 })?;
71 SignedEntityType::CardanoImmutableFilesFull(beacon)
72 }
73 SignedEntityTypeDiscriminants::CardanoTransactions => {
74 #[derive(Deserialize)]
75 struct CardanoTransactionsBeacon {
76 epoch: Epoch,
77 block_number: BlockNumber,
78 }
79
80 let beacon: CardanoTransactionsBeacon =
81 serde_json::from_str(beacon_str).map_err(|e| {
82 HydrationError::InvalidData(format!(
83 "Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
84 ))
85 })?;
86 SignedEntityType::CardanoTransactions(beacon.epoch, beacon.block_number)
87 }
88 SignedEntityTypeDiscriminants::CardanoBlocksTransactions => {
89 #[derive(Deserialize)]
90 struct CardanoBlocksTransactionsBeacon {
91 epoch: Epoch,
92 block_number: BlockNumber,
93 }
94
95 let beacon: CardanoBlocksTransactionsBeacon = serde_json::from_str(beacon_str)
96 .map_err(|e| {
97 HydrationError::InvalidData(format!(
98 "Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
99 ))
100 })?;
101 SignedEntityType::CardanoBlocksTransactions(beacon.epoch, beacon.block_number)
102 }
103 SignedEntityTypeDiscriminants::CardanoDatabase => {
104 let beacon: CardanoDbBeacon = serde_json::from_str(beacon_str).map_err(|e| {
105 HydrationError::InvalidData(format!(
106 "Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
107 ))
108 })?;
109 SignedEntityType::CardanoDatabase(beacon)
110 }
111 };
112
113 Ok(signed_entity)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn hydrate_cardano_transactions_signed_entity_type() {
123 let expected = SignedEntityType::CardanoTransactions(Epoch(35), BlockNumber(77));
124 let signed_entity = Hydrator::hydrate_signed_entity_type(
125 SignedEntityTypeDiscriminants::CardanoTransactions.index(),
126 &expected.get_json_beacon().unwrap(),
127 )
128 .unwrap();
129
130 assert_eq!(expected, signed_entity);
131 }
132
133 #[test]
134 fn hydrate_cardano_blocks_transactions_signed_entity_type() {
135 let expected = SignedEntityType::CardanoBlocksTransactions(Epoch(37), BlockNumber(79));
136 let signed_entity = Hydrator::hydrate_signed_entity_type(
137 SignedEntityTypeDiscriminants::CardanoBlocksTransactions.index(),
138 &expected.get_json_beacon().unwrap(),
139 )
140 .unwrap();
141
142 assert_eq!(expected, signed_entity);
143 }
144
145 #[test]
146 fn hydrate_cardano_database_signed_entity_type() {
147 let expected = SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(84, 239));
148 let signed_entity = Hydrator::hydrate_signed_entity_type(
149 SignedEntityTypeDiscriminants::CardanoDatabase.index(),
150 &expected.get_json_beacon().unwrap(),
151 )
152 .unwrap();
153
154 assert_eq!(expected, signed_entity);
155 }
156}