From eb7ff6495d08e3c571a9e3ea96ec3ab718abcdb2 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi <106849+romac@users.noreply.github.com> Date: Wed, 4 Oct 2023 18:06:15 +0200 Subject: [PATCH 1/2] rpc: Add `FromStr`, `Serialize` and `Deserialize` instances to `CompatMode` --- rpc/src/client/compat.rs | 61 ++++++++++++++++++++++++++++++++++++++++ rpc/src/error.rs | 10 +++++++ 2 files changed, 71 insertions(+) diff --git a/rpc/src/client/compat.rs b/rpc/src/client/compat.rs index 05824d875..0a419cf9f 100644 --- a/rpc/src/client/compat.rs +++ b/rpc/src/client/compat.rs @@ -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 tendermint::Version; @@ -14,6 +17,12 @@ pub enum CompatMode { V0_34, /// Use version 0.37 of the protocol. 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 { @@ -64,6 +73,45 @@ impl fmt::Display for CompatMode { } } +impl FromStr for CompatMode { + type Err = Error; + + fn from_str(s: &str) -> Result { + 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(deserializer: D) -> Result + 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(&self, serializer: S) -> Result + where + S: Serializer, + { + self.to_string().serialize(serializer) + } +} + #[cfg(test)] mod tests { use super::CompatMode; @@ -100,4 +148,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::().unwrap(), CompatMode::V0_34); + assert_eq!("0.37".parse::().unwrap(), CompatMode::V0_37); + + let res = "0.33".parse::(); + assert!(res.is_err()); + let res = "0.38".parse::(); + assert!(res.is_err()); + let res = "foobar".parse::(); + assert!(res.is_err()); + } } diff --git a/rpc/src/error.rs b/rpc/src/error.rs index 1e42e461d..7674fb1a8 100644 --- a/rpc/src/error.rs +++ b/rpc/src/error.rs @@ -216,6 +216,16 @@ define_error! { | e | { format_args!("unsupported Tendermint version reported by the node: {}", e.version) }, + + InvalidCompatMode + { + mode: String, + supported: &'static str, + } + | e | { + format_args!("invalid compatibility mode: '{}' (supported: {})", + e.mode, e.supported) + }, } } From fd29710ebece9bd2e004e5c0b5bcf35bc30df423 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 1 Nov 2023 11:08:23 +0100 Subject: [PATCH 2/2] Add changelog entry --- .../unreleased/improvements/1374-compatmode-instances.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/unreleased/improvements/1374-compatmode-instances.md diff --git a/.changelog/unreleased/improvements/1374-compatmode-instances.md b/.changelog/unreleased/improvements/1374-compatmode-instances.md new file mode 100644 index 000000000..1d0033745 --- /dev/null +++ b/.changelog/unreleased/improvements/1374-compatmode-instances.md @@ -0,0 +1,3 @@ +- `[tendermint-rpc]` Add `FromStr`, `Serialize` and `Deserialize` instances + to `CompatMode` ([\#1374](https://github.com/informalsystems/tendermint- + rs/issues/1374)) \ No newline at end of file