ibc_testkit/testapp/ibc/clients/mock/
header.rs1use alloc::string::ToString;
2use core::fmt::{Display, Error as FmtError, Formatter};
3
4use ibc::core::client::types::Height;
5use ibc::core::host::types::error::DecodingError;
6use ibc::core::primitives::Timestamp;
7use ibc::primitives::proto::{Any, Protobuf};
8
9use crate::testapp::ibc::clients::mock::proto::Header as RawMockHeader;
10use crate::utils::year_2023;
11
12pub const MOCK_HEADER_TYPE_URL: &str = "/ibc.mock.Header";
13
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16pub struct MockHeader {
17 pub height: Height,
18 pub timestamp: Timestamp,
19}
20
21impl Default for MockHeader {
22 fn default() -> Self {
23 Self {
24 height: Height::min(0),
25 timestamp: year_2023(),
26 }
27 }
28}
29
30impl Display for MockHeader {
31 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
32 write!(
33 f,
34 "MockHeader {{ height: {}, timestamp: {} }}",
35 self.height, self.timestamp
36 )
37 }
38}
39
40impl Protobuf<RawMockHeader> for MockHeader {}
41
42impl TryFrom<RawMockHeader> for MockHeader {
43 type Error = DecodingError;
44
45 fn try_from(raw: RawMockHeader) -> Result<Self, Self::Error> {
46 Ok(Self {
47 height: raw
48 .height
49 .ok_or(DecodingError::missing_raw_data("mock header height"))?
50 .try_into()?,
51 timestamp: Timestamp::from_nanoseconds(raw.timestamp),
52 })
53 }
54}
55
56impl From<MockHeader> for RawMockHeader {
57 fn from(value: MockHeader) -> Self {
58 Self {
59 height: Some(value.height.into()),
60 timestamp: value.timestamp.nanoseconds(),
61 }
62 }
63}
64
65impl MockHeader {
66 pub fn height(&self) -> Height {
67 self.height
68 }
69
70 pub fn new(height: Height) -> Self {
71 Self {
72 height,
73 timestamp: year_2023(),
74 }
75 }
76
77 pub fn with_current_timestamp(self) -> Self {
78 Self {
79 timestamp: Timestamp::now(),
80 ..self
81 }
82 }
83
84 pub fn with_timestamp(self, timestamp: Timestamp) -> Self {
85 Self { timestamp, ..self }
86 }
87}
88
89impl Protobuf<Any> for MockHeader {}
90
91impl TryFrom<Any> for MockHeader {
92 type Error = DecodingError;
93
94 fn try_from(raw: Any) -> Result<Self, Self::Error> {
95 if let MOCK_HEADER_TYPE_URL = raw.type_url.as_str() {
96 Protobuf::<RawMockHeader>::decode_vec(&raw.value).map_err(Into::into)
97 } else {
98 Err(DecodingError::MismatchedResourceName {
99 expected: MOCK_HEADER_TYPE_URL.to_string(),
100 actual: raw.type_url,
101 })
102 }
103 }
104}
105
106impl From<MockHeader> for Any {
107 fn from(header: MockHeader) -> Self {
108 Self {
109 type_url: MOCK_HEADER_TYPE_URL.to_string(),
110 value: Protobuf::<RawMockHeader>::encode_vec(header),
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117
118 use super::*;
119
120 #[test]
121 fn encode_any() {
122 let header = MockHeader::new(Height::new(1, 10).expect("Never fails"));
123 let bytes = <MockHeader as Protobuf<Any>>::encode_vec(header);
124
125 assert_eq!(
126 &bytes,
127 &[
128 10, 16, 47, 105, 98, 99, 46, 109, 111, 99, 107, 46, 72, 101, 97, 100, 101, 114, 18,
129 16, 10, 4, 8, 1, 16, 10, 16, 128, 128, 136, 158, 189, 200, 129, 155, 23
130 ]
131 );
132 }
133}