evidentsource_client/conversions/
state_view.rs1use evidentsource_core::domain::{DatabaseName, EventSelector, StateView, StateViewName};
4
5use crate::com::evidentsource as proto;
6
7use super::error::ConversionError;
8use super::timestamps::timestamp_to_datetime;
9
10impl TryFrom<proto::StateView> for StateView {
15 type Error = ConversionError;
16
17 fn try_from(proto: proto::StateView) -> Result<Self, Self::Error> {
18 let identity = proto
19 .identity
20 .ok_or_else(|| ConversionError::missing_field("StateView", "identity"))?;
21
22 let database = DatabaseName::new(&identity.database_name)?;
23 let name = StateViewName::new(&identity.state_view_name)?;
24
25 let event_selector_proto = proto
26 .event_selector
27 .ok_or_else(|| ConversionError::missing_field("StateView", "event_selector"))?;
28 let event_selector = EventSelector::try_from(event_selector_proto)?;
29
30 let last_modified_timestamp = proto.last_modified.map(timestamp_to_datetime).transpose()?;
31
32 let last_modified_revision = if proto.last_modified_revision > 0 {
33 Some(proto.last_modified_revision)
34 } else {
35 None
36 };
37
38 let content = match proto.content {
39 Some(proto::state_view::Content::Data(bytes)) => Some(bytes),
40 Some(proto::state_view::Content::Url(_)) => {
41 None
43 }
44 None => None,
45 };
46
47 Ok(StateView {
48 database,
49 name,
50 version: identity.state_view_version,
51 event_selector,
52 last_modified_revision,
53 last_modified_timestamp,
54 content_type: proto.content_type,
55 content_schema_url: proto.content_schema_url.filter(|s| !s.is_empty()),
56 content,
57 })
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_state_view_conversion() {
67 let proto = proto::StateView {
68 identity: Some(proto::StateViewIdentity {
69 database_name: "test-db".to_string(),
70 state_view_name: "test-view".to_string(),
71 state_view_version: 1,
72 }),
73 event_selector: Some(proto::EventSelector {
74 selector: Some(proto::event_selector::Selector::Equals(
75 proto::EventAttribute {
76 attribute: Some(proto::event_attribute::Attribute::Stream(
77 "my-stream".to_string(),
78 )),
79 },
80 )),
81 }),
82 last_modified: None,
83 last_modified_revision: 0,
84 content_type: "application/json".to_string(),
85 content_schema_url: None,
86 content: Some(proto::state_view::Content::Data(
87 b"{\"count\": 42}".to_vec(),
88 )),
89 };
90
91 let domain: StateView = proto.try_into().unwrap();
92 assert_eq!(domain.database.as_str(), "test-db");
93 assert_eq!(domain.name.as_str(), "test-view");
94 assert_eq!(domain.version, 1);
95 assert_eq!(domain.content_type, "application/json");
96 assert!(domain.content.is_some());
97 }
98}