tendermint_rpc/client/
compat.rs1use core::fmt;
4use core::str::FromStr;
5
6use serde::{de::Deserializer, Deserialize, Serialize, Serializer};
7
8use tendermint::Version;
9
10use crate::prelude::*;
11use crate::Error;
12
13#[derive(Copy, Clone, Debug, PartialEq, Eq)]
15pub enum CompatMode {
16 V0_34,
18 V0_37,
20 V0_38,
22 }
29
30impl Default for CompatMode {
31 fn default() -> Self {
32 CompatMode::latest()
33 }
34}
35
36impl CompatMode {
37 pub const fn latest() -> Self {
39 Self::V0_38
40 }
41
42 pub fn from_version(tendermint_version: Version) -> Result<CompatMode, Error> {
56 let raw_version: String = tendermint_version.into();
57 let version = semver::Version::parse(raw_version.trim_start_matches('v'))
58 .map_err(|_| Error::invalid_tendermint_version(raw_version))?;
59
60 match (version.major, version.minor) {
61 (0, 34) => Ok(CompatMode::V0_34),
62 (0, 37) => Ok(CompatMode::V0_37),
63 (0, 38) => Ok(CompatMode::V0_38),
64 _ => Err(Error::unsupported_tendermint_version(version.to_string())),
65 }
66 }
67}
68
69impl fmt::Display for CompatMode {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 CompatMode::V0_34 => f.write_str("v0.34"),
73 CompatMode::V0_37 => f.write_str("v0.37"),
74 CompatMode::V0_38 => f.write_str("v0.38"),
75 }
76 }
77}
78
79impl FromStr for CompatMode {
80 type Err = Error;
81
82 fn from_str(s: &str) -> Result<Self, Self::Err> {
83 const VALID_COMPAT_MODES: &str = "v0.34, v0.37, v0.38";
84
85 match s.trim_start_matches('v') {
87 "0.34" => Ok(CompatMode::V0_34),
88 "0.37" => Ok(CompatMode::V0_37),
89 "0.38" => Ok(CompatMode::V0_38),
90 _ => Err(Error::invalid_compat_mode(
91 s.to_string(),
92 VALID_COMPAT_MODES,
93 )),
94 }
95 }
96}
97
98impl<'de> Deserialize<'de> for CompatMode {
99 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
100 where
101 D: Deserializer<'de>,
102 {
103 use serde::de;
104
105 let s = String::deserialize(deserializer)?;
106 FromStr::from_str(&s).map_err(de::Error::custom)
107 }
108}
109
110impl Serialize for CompatMode {
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: Serializer,
114 {
115 self.to_string().serialize(serializer)
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::CompatMode;
122 use crate::prelude::*;
123 use tendermint::Version;
124
125 fn parse_version(s: &str) -> Version {
126 let json = format!("\"{s}\"");
127 serde_json::from_str(&json).unwrap()
128 }
129
130 #[test]
131 fn test_parse_version_for_compat_mode() {
132 assert_eq!(
133 CompatMode::from_version(parse_version("v0.34.16")).unwrap(),
134 CompatMode::V0_34
135 );
136 assert_eq!(
137 CompatMode::from_version(parse_version("v0.37.0-pre1")).unwrap(),
138 CompatMode::V0_37
139 );
140 assert_eq!(
141 CompatMode::from_version(parse_version("v0.37.0")).unwrap(),
142 CompatMode::V0_37
143 );
144 assert_eq!(
145 CompatMode::from_version(parse_version("v0.38.0")).unwrap(),
146 CompatMode::V0_38
147 );
148 let res = CompatMode::from_version(parse_version("v0.39.0"));
149 assert!(res.is_err());
150 let res = CompatMode::from_version(parse_version("v1.0.0"));
151 assert!(res.is_err());
152 let res = CompatMode::from_version(parse_version("poobah"));
153 assert!(res.is_err());
154 }
155
156 #[test]
157 fn test_from_str() {
158 assert_eq!("0.34".parse::<CompatMode>().unwrap(), CompatMode::V0_34);
159 assert_eq!("0.37".parse::<CompatMode>().unwrap(), CompatMode::V0_37);
160 assert_eq!("0.38".parse::<CompatMode>().unwrap(), CompatMode::V0_38);
161
162 let res = "0.33".parse::<CompatMode>();
163 assert!(res.is_err());
164 let res = "0.39".parse::<CompatMode>();
165 assert!(res.is_err());
166 let res = "foobar".parse::<CompatMode>();
167 assert!(res.is_err());
168 }
169}