1pub use prost_types::{Duration, Timestamp};
3pub use tendermint_proto::{
4 abci::{
5 response_apply_snapshot_chunk::Result as ApplySnapshotChunkResult,
6 response_offer_snapshot::Result as OfferSnapshotResult, BlockParams, CheckTxType,
7 ConsensusParams, Event, EventAttribute, Evidence, LastCommitInfo,
8 RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestCommit,
9 RequestDeliverTx, RequestEcho, RequestEndBlock, RequestFlush, RequestInfo,
10 RequestInitChain, RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot,
11 RequestQuery, RequestSetOption, ResponseApplySnapshotChunk, ResponseBeginBlock,
12 ResponseCheckTx, ResponseCommit, ResponseDeliverTx, ResponseEcho, ResponseEndBlock,
13 ResponseFlush, ResponseInfo, ResponseInitChain, ResponseListSnapshots,
14 ResponseLoadSnapshotChunk, ResponseOfferSnapshot, ResponseQuery, ResponseSetOption,
15 Snapshot, Validator, ValidatorUpdate, VoteInfo,
16 },
17 crypto::{public_key::Sum, ProofOp, ProofOps, PublicKey},
18 types::{BlockId, EvidenceParams, Header, PartSetHeader, ValidatorParams, VersionParams},
19 version::Consensus,
20};
21
22use std::{
23 convert::TryFrom,
24 io::{Error, ErrorKind, Result},
25};
26
27use bytes::{Buf, BufMut};
28use integer_encoding::VarInt;
29use prost::Message;
30
31pub(crate) fn decode<M, B>(buf: &mut B) -> Result<Option<M>>
33where
34 M: Message + Default,
35 B: Buf,
36{
37 if buf.remaining() == 0 {
38 return Ok(None);
40 }
41
42 let (len, advance) =
43 i64::decode_var(buf.chunk()).ok_or_else(|| Error::from(ErrorKind::InvalidData))?;
44
45 assert!(len >= 0, "Length of protobuf message must not be negative");
46
47 if len == 0 {
48 buf.advance(advance);
50 return Ok(None);
51 }
52
53 let len = usize::try_from(len).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
54
55 if buf.remaining() < (advance + len) {
56 return Ok(None);
58 }
59
60 buf.advance(advance);
61 let bytes = buf.copy_to_bytes(len);
62 let message = M::decode(bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
63
64 Ok(Some(message))
65}
66
67pub(crate) fn encode<M, B>(message: M, buf: &mut B) -> Result<()>
68where
69 M: Message,
70 B: BufMut,
71{
72 let len = i64::try_from(message.encoded_len()).map_err(|e| Error::new(ErrorKind::Other, e))?;
73 let len_bytes = len.encode_var_vec();
74
75 buf.put(len_bytes.as_ref());
76
77 message
78 .encode(buf)
79 .map_err(|e| Error::new(ErrorKind::Other, e))?;
80
81 Ok(())
82}
83
84#[cfg(test)]
85mod tests {
86 use bytes::{Buf, BytesMut};
87 use tendermint_proto::abci::{request::Value, Request, RequestFlush, RequestInfo};
88
89 use super::{decode, encode};
90
91 #[test]
92 fn check_decoding() {
93 let mut buf = BytesMut::new();
94 buf.extend_from_slice(&[
95 30, 26, 13, 10, 7, 118, 48, 46, 51, 52, 46, 51, 16, 11, 24, 8, 4, 18, 0,
96 ]);
97
98 let request = decode::<Request, _>(&mut buf);
99 assert!(request.is_ok());
100 let request = request.unwrap();
101 assert!(request.is_some());
102 let request = request.unwrap();
103 assert_eq!(
104 request,
105 Request {
106 value: Some(Value::Info(RequestInfo {
107 version: "v0.34.3".to_string(),
108 block_version: 11,
109 p2p_version: 8
110 }))
111 }
112 );
113
114 let request = decode::<Request, _>(&mut buf);
115 assert!(request.is_ok());
116 let request = request.unwrap();
117 assert!(request.is_some());
118 let request = request.unwrap();
119 assert_eq!(
120 request,
121 Request {
122 value: Some(Value::Flush(RequestFlush {}))
123 }
124 );
125
126 let request = decode::<Request, _>(&mut buf);
127 assert!(request.is_ok());
128 let request = request.unwrap();
129 assert!(request.is_none());
130
131 assert_eq!(0, buf.remaining());
132 }
133
134 #[test]
135 fn check_encoding() {
136 let mut buf = BytesMut::new();
137
138 let request = Request {
139 value: Some(Value::Flush(RequestFlush {})),
140 };
141 encode(request, &mut buf).unwrap();
142 assert_eq!([4, 18, 0], buf.chunk());
143
144 buf.clear();
145
146 let request = Request {
147 value: Some(Value::Info(RequestInfo {
148 version: "v0.34.3".to_string(),
149 block_version: 11,
150 p2p_version: 8,
151 })),
152 };
153
154 encode(request, &mut buf).unwrap();
155 assert_eq!(
156 [30, 26, 13, 10, 7, 118, 48, 46, 51, 52, 46, 51, 16, 11, 24, 8],
157 buf.chunk()
158 );
159 }
160}