Skip to content

Commit

Permalink
Port "rpc: Add FromStr, Serialize and Deserialize instances to Compat…
Browse files Browse the repository at this point in the history
…Mode" (tendermint-rs#1367) (cometbft#27)
  • Loading branch information
romac authored Apr 25, 2024
1 parent 20b4428 commit 03f689b
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `[cometbft-rpc]` Add `FromStr`, `Serialize` and `Deserialize` instances to `CompatMode` ([\#21](https://github.com/cometbft/cometbft-rs/issues/21))
61 changes: 61 additions & 0 deletions rpc/src/client/compat.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Support for dynamic compatibility with older protocol versions.
use core::fmt;
use core::str::FromStr;

use serde::{de::Deserializer, Deserialize, Serialize, Serializer};

use cometbft::Version;

Expand All @@ -15,6 +18,12 @@ pub enum CompatMode {
/// Use a compatibility mode for the RPC protocol used since CometBFT 0.37.
/// This is the default mode that has persisted into CometBFT 1.0.
V0_37,
// NOTE: When adding a newer version, do not forget to update:
// - CompatMode::latest()
// - CompatMode::from_version()
// - impl Display for CompatMode
// - impl FromStr for CompatMode
// - The tests
}

impl Default for CompatMode {
Expand Down Expand Up @@ -66,6 +75,45 @@ impl fmt::Display for CompatMode {
}
}

impl FromStr for CompatMode {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
const VALID_COMPAT_MODES: &str = "v0.34, v0.37";

// Trim leading 'v', if present
match s.trim_start_matches('v') {
"0.34" => Ok(CompatMode::V0_34),
"0.37" => Ok(CompatMode::V0_37),
_ => Err(Error::invalid_compat_mode(
s.to_string(),
VALID_COMPAT_MODES,
)),
}
}
}

impl<'de> Deserialize<'de> for CompatMode {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de;

let s = String::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)
}
}

impl Serialize for CompatMode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.to_string().serialize(serializer)
}
}

#[cfg(test)]
mod tests {
use super::CompatMode;
Expand Down Expand Up @@ -112,4 +160,17 @@ mod tests {
let res = CompatMode::from_version(parse_version("poobah"));
assert!(res.is_err());
}

#[test]
fn test_from_str() {
assert_eq!("0.34".parse::<CompatMode>().unwrap(), CompatMode::V0_34);
assert_eq!("0.37".parse::<CompatMode>().unwrap(), CompatMode::V0_37);

let res = "0.33".parse::<CompatMode>();
assert!(res.is_err());
let res = "0.38".parse::<CompatMode>();
assert!(res.is_err());
let res = "foobar".parse::<CompatMode>();
assert!(res.is_err());
}
}
10 changes: 10 additions & 0 deletions rpc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,16 @@ define_error! {
| e | {
format_args!("unsupported CometBFT version reported by the node: {}", e.version)
},

InvalidCompatMode
{
mode: String,
supported: &'static str,
}
| e | {
format_args!("invalid compatibility mode: '{}' (supported: {})",
e.mode, e.supported)
},
}
}

Expand Down

0 comments on commit 03f689b

Please sign in to comment.