Skip to main content

codama_nodes/shared/
is_signer.rs

1use crate::IsSigner;
2use serde::{Deserialize, Serialize};
3
4impl From<bool> for IsSigner {
5    fn from(value: bool) -> Self {
6        match value {
7            false => Self::False,
8            true => Self::True,
9        }
10    }
11}
12
13// The spec's literalUnion doesn't carry a notion of "default
14// variant", so the generated `IsSigner` shell has no
15// `#[derive(Default)]`. The default member is a Rust-side choice and
16// lives here.
17#[allow(clippy::derivable_impls)]
18impl Default for IsSigner {
19    fn default() -> Self {
20        IsSigner::False
21    }
22}
23
24// `IsSigner` serialises to a heterogeneous JSON value: real
25// booleans `true`/`false` for the boolean variants and the string
26// `"either"` for the third. Serde's derive + `rename_all` machinery
27// can't express that — `rename` only produces strings — so the
28// Serialize/Deserialize impls are hand-written. The generator emits
29// the enum shell with non-serde derives only so these impls don't
30// clash with derived ones.
31impl Serialize for IsSigner {
32    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33    where
34        S: serde::Serializer,
35    {
36        match self {
37            IsSigner::False => serializer.serialize_bool(false),
38            IsSigner::True => serializer.serialize_bool(true),
39            IsSigner::Either => serializer.serialize_str("either"),
40        }
41    }
42}
43
44impl<'de> Deserialize<'de> for IsSigner {
45    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
46    where
47        D: serde::Deserializer<'de>,
48    {
49        struct IsSignerVisitor;
50
51        impl serde::de::Visitor<'_> for IsSignerVisitor {
52            type Value = IsSigner;
53
54            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
55                formatter.write_str("a boolean or the string 'either'")
56            }
57
58            fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
59            where
60                E: serde::de::Error,
61            {
62                Ok(IsSigner::from(value))
63            }
64
65            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
66            where
67                E: serde::de::Error,
68            {
69                match value {
70                    "either" => Ok(IsSigner::Either),
71                    _ => Err(E::custom(format!("unexpected value: {value}"))),
72                }
73            }
74        }
75
76        deserializer.deserialize_any(IsSignerVisitor)
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn to_json() {
86        assert_eq!(serde_json::to_string(&IsSigner::True).unwrap(), "true");
87        assert_eq!(serde_json::to_string(&IsSigner::False).unwrap(), "false");
88        assert_eq!(
89            serde_json::to_string(&IsSigner::Either).unwrap(),
90            "\"either\""
91        );
92    }
93
94    #[test]
95    fn from_json() {
96        assert_eq!(
97            serde_json::from_str::<IsSigner>("true").unwrap(),
98            IsSigner::True
99        );
100        assert_eq!(
101            serde_json::from_str::<IsSigner>("false").unwrap(),
102            IsSigner::False
103        );
104        assert_eq!(
105            serde_json::from_str::<IsSigner>("\"either\"").unwrap(),
106            IsSigner::Either
107        );
108    }
109
110    #[test]
111    fn from_bool() {
112        assert_eq!(IsSigner::from(true), IsSigner::True);
113        assert_eq!(IsSigner::from(false), IsSigner::False);
114    }
115
116    #[test]
117    fn default_is_false() {
118        assert_eq!(IsSigner::default(), IsSigner::False);
119    }
120}