1use serde::{
2 de::{DeserializeOwned, Deserializer, Error as _},
3 ser::{Error as _, Serializer},
4 Deserialize, Serialize,
5};
6
7pub trait FromStringOrInteger: Sized {
18 type Binary: Serialize + DeserializeOwned;
19 type Integer: Serialize + DeserializeOwned;
20
21 fn from_binary(b: Self::Binary) -> anyhow::Result<Self>;
22 fn from_string(s: String) -> anyhow::Result<Self>;
23 fn from_integer(i: Self::Integer) -> anyhow::Result<Self>;
24
25 fn to_binary(&self) -> anyhow::Result<Self::Binary>;
26 fn to_string(&self) -> anyhow::Result<String>;
27}
28
29#[macro_export]
35macro_rules! impl_serde_from_string_or_integer {
36 ($t:ty) => {
37 impl serde::Serialize for $t {
38 fn serialize<S: serde::ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
39 $crate::ser::string_or_integer::serialize(self, s)
40 }
41 }
42
43 impl<'de> serde::Deserialize<'de> for $t {
44 fn deserialize<D: serde::de::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
45 $crate::ser::string_or_integer::deserialize(d)
46 }
47 }
48 };
49}
50pub use crate::impl_serde_from_string_or_integer;
51
52pub mod string_or_integer {
57 use super::*;
58
59 #[derive(Debug, Deserialize)]
60 #[serde(untagged)]
61 enum StringOrInteger<I> {
62 String(String),
63 Integer(I),
64 }
65
66 pub fn serialize<T: FromStringOrInteger, S: Serializer>(
67 t: &T,
68 s: S,
69 ) -> Result<S::Ok, S::Error> {
70 if s.is_human_readable() {
71 t.to_string().map_err(S::Error::custom)?.serialize(s)
72 } else {
73 t.to_binary().map_err(S::Error::custom)?.serialize(s)
74 }
75 }
76
77 pub fn deserialize<'a, T: FromStringOrInteger, D: Deserializer<'a>>(
78 d: D,
79 ) -> Result<T, D::Error> {
80 if d.is_human_readable() {
81 match StringOrInteger::deserialize(d)? {
82 StringOrInteger::String(s) => T::from_string(s).map_err(D::Error::custom),
83 StringOrInteger::Integer(i) => T::from_integer(i).map_err(D::Error::custom),
84 }
85 } else {
86 T::from_binary(T::Binary::deserialize(d)?).map_err(D::Error::custom)
87 }
88 }
89}