tendermint/abci/
code.rs

1use core::{fmt, num::NonZeroU32};
2
3use serde::{
4    de::{Deserialize, Deserializer, Visitor},
5    Serialize, Serializer,
6};
7
8/// ABCI application response codes.
9///
10/// These presently use 0 for success and non-zero for errors:
11///
12/// <https://tendermint.com/docs/spec/abci/abci.html#errors>
13///
14/// Note that in the future there may potentially be non-zero success codes.
15#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Default)]
16pub enum Code {
17    /// Success
18    #[default]
19    Ok,
20
21    /// Error codes
22    Err(NonZeroU32),
23}
24
25impl Code {
26    /// Was the response OK?
27    pub fn is_ok(self) -> bool {
28        match self {
29            Code::Ok => true,
30            Code::Err(_) => false,
31        }
32    }
33
34    /// Was the response an error?
35    pub fn is_err(self) -> bool {
36        !self.is_ok()
37    }
38
39    /// Get the integer error value for this code
40    pub fn value(self) -> u32 {
41        u32::from(self)
42    }
43}
44
45impl From<u32> for Code {
46    fn from(value: u32) -> Code {
47        match NonZeroU32::new(value) {
48            Some(value) => Code::Err(value),
49            None => Code::Ok,
50        }
51    }
52}
53
54impl From<Code> for u32 {
55    fn from(code: Code) -> u32 {
56        match code {
57            Code::Ok => 0,
58            Code::Err(err) => err.get(),
59        }
60    }
61}
62
63impl Serialize for Code {
64    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
65        self.value().serialize(serializer)
66    }
67}
68
69impl<'de> Deserialize<'de> for Code {
70    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
71    where
72        D: Deserializer<'de>,
73    {
74        struct CodeVisitor;
75
76        impl<'de> Visitor<'de> for CodeVisitor {
77            type Value = Code;
78
79            fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80                fmt.write_str("integer or string")
81            }
82
83            fn visit_u64<E>(self, val: u64) -> Result<Self::Value, E>
84            where
85                E: serde::de::Error,
86            {
87                Ok(Code::from(val as u32))
88            }
89
90            fn visit_str<E>(self, val: &str) -> Result<Self::Value, E>
91            where
92                E: serde::de::Error,
93            {
94                match val.parse::<u64>() {
95                    Ok(val) => self.visit_u64(val),
96                    Err(_) => Err(E::custom("failed to parse integer")),
97                }
98            }
99        }
100
101        deserializer.deserialize_any(CodeVisitor)
102    }
103}