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::CardanoDatabase => {
89 let beacon: CardanoDbBeacon = serde_json::from_str(beacon_str).map_err(|e| {
90 HydrationError::InvalidData(format!(
91 "Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
92 ))
93 })?;
94 SignedEntityType::CardanoDatabase(beacon)
95 }
96 };
97
98 Ok(signed_entity)
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn hydrate_cardano_transaction_signed_entity_type() {
108 let expected = SignedEntityType::CardanoTransactions(Epoch(35), BlockNumber(77));
109 let signed_entity = Hydrator::hydrate_signed_entity_type(
110 SignedEntityTypeDiscriminants::CardanoTransactions.index(),
111 &expected.get_json_beacon().unwrap(),
112 )
113 .unwrap();
114
115 assert_eq!(expected, signed_entity);
116 }
117
118 #[test]
119 fn hydrate_cardano_database_signed_entity_type() {
120 let expected = SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(84, 239));
121 let signed_entity = Hydrator::hydrate_signed_entity_type(
122 SignedEntityTypeDiscriminants::CardanoDatabase.index(),
123 &expected.get_json_beacon().unwrap(),
124 )
125 .unwrap();
126
127 assert_eq!(expected, signed_entity);
128 }
129}