1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use chrono::{DateTime, Utc};

use mithril_common::{crypto_helper::ProtocolInitializer, entities::Epoch};
use mithril_persistence::sqlite::{HydrationError, Projection, SqLiteEntity};

/// Protocol initializer.
#[derive(Debug)]
pub struct ProtocolInitializerRecord {
    /// Epoch
    pub epoch: Epoch,

    /// Protocol Initializer
    pub protocol_initializer: ProtocolInitializer,

    /// DateTime of the record creation.
    pub created_at: DateTime<Utc>,
}

impl SqLiteEntity for ProtocolInitializerRecord {
    fn hydrate(row: sqlite::Row) -> Result<Self, HydrationError>
    where
        Self: Sized,
    {
        let epoch_int = row.read::<i64, _>(0);
        let protocol = row.read::<&str, _>(1);
        let datetime = &row.read::<&str, _>(2);

        let record = Self {
            protocol_initializer: serde_json::from_str(protocol).map_err(|e| {
                HydrationError::InvalidData(format!(
                    "Could not cast string ({}) to ProtocolInitializer. Error: '{e}'",
                    protocol
                ))
            })?,
            epoch: Epoch(epoch_int.try_into().map_err(|e| {
                HydrationError::InvalidData(format!(
                    "Could not cast i64 ({epoch_int}) to u64. Error: '{e}'"
                ))
            })?),
            created_at: DateTime::parse_from_rfc3339(datetime)
                .map_err(|e| {
                    HydrationError::InvalidData(format!(
                        "Could not turn string '{datetime}' to rfc3339 Datetime. Error: {e}"
                    ))
                })?
                .with_timezone(&Utc),
        };

        Ok(record)
    }

    fn get_projection() -> Projection {
        let mut projection = Projection::default();
        projection.add_field("epoch", "{:protocol_initializer:}.epoch", "integer");
        projection.add_field("protocol", "{:protocol_initializer:}.protocol", "integer");
        projection.add_field("created_at", "{:protocol_initializer:}.created_at", "text");

        projection
    }
}