tendermint/block/
round.rs

1use core::{
2    fmt::{self, Debug, Display},
3    str::FromStr,
4};
5
6use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
7
8use crate::{error::Error, prelude::*};
9
10/// Block round for a particular chain
11#[derive(Copy, Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
12pub struct Round(u32);
13
14impl TryFrom<i32> for Round {
15    type Error = Error;
16
17    fn try_from(value: i32) -> Result<Self, Self::Error> {
18        Ok(Round(value.try_into().map_err(Error::negative_round)?))
19    }
20}
21
22impl From<Round> for i32 {
23    fn from(value: Round) -> Self {
24        value.value() as i32 // does not overflow. The value is <= i32::MAX
25    }
26}
27
28impl TryFrom<u32> for Round {
29    type Error = Error;
30
31    fn try_from(value: u32) -> Result<Self, Self::Error> {
32        let _val: i32 = value.try_into().map_err(Error::integer_overflow)?;
33
34        Ok(Round(value))
35    }
36}
37
38impl From<Round> for u32 {
39    fn from(value: Round) -> Self {
40        value.value()
41    }
42}
43
44impl From<u16> for Round {
45    fn from(value: u16) -> Self {
46        Round(value as u32)
47    }
48}
49
50impl From<u8> for Round {
51    fn from(value: u8) -> Self {
52        Round(value as u32)
53    }
54}
55
56impl Round {
57    /// Get inner integer value. Alternative to `.0` or `.into()`
58    pub fn value(&self) -> u32 {
59        self.0
60    }
61
62    /// Increment the block round by 1
63    pub fn increment(self) -> Self {
64        Round::try_from(self.0.checked_add(1).expect("round overflow")).unwrap()
65    }
66}
67
68impl Debug for Round {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        write!(f, "block::Round({})", self.0)
71    }
72}
73
74impl Display for Round {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        write!(f, "{}", self.0)
77    }
78}
79
80impl FromStr for Round {
81    type Err = Error;
82
83    fn from_str(s: &str) -> Result<Self, Error> {
84        Round::try_from(
85            s.parse::<u32>()
86                .map_err(|e| Error::parse_int(s.to_string(), e))?,
87        )
88    }
89}
90
91impl<'de> Deserialize<'de> for Round {
92    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
93        Self::from_str(&String::deserialize(deserializer)?)
94            .map_err(|e| D::Error::custom(format!("{e}")))
95    }
96}
97
98impl Serialize for Round {
99    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
100        u32::from(*self).to_string().serialize(serializer)
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn increment_by_one() {
110        assert_eq!(Round::default().increment().value(), 1);
111    }
112
113    #[test]
114    fn avoid_try_unwrap_dance() {
115        assert_eq!(
116            Round::try_from(2_u32).unwrap().value(),
117            Round::from(2_u16).value()
118        );
119    }
120}