1pub mod daily_withdrawal_limit;
2#[cfg(all(feature = "withdrawals-contract", feature = "system_contracts"))]
3mod document_try_into_asset_unlock_base_transaction_info;
4
5use bincode::{Decode, Encode};
6use serde_repr::{Deserialize_repr, Serialize_repr};
7
8#[repr(u8)]
9#[derive(
10 Serialize_repr, Deserialize_repr, PartialEq, Eq, Clone, Copy, Debug, Encode, Decode, Default,
11)]
12pub enum Pooling {
13 #[default]
14 Never = 0,
15 IfAvailable = 1,
16 Standard = 2,
17}
18
19pub type WithdrawalTransactionIndex = u64;
21
22pub type WithdrawalTransactionIndexAndBytes = (WithdrawalTransactionIndex, Vec<u8>);
24
25#[cfg(feature = "serde-conversion")]
38pub mod pooling_serde {
39 use super::Pooling;
40 use serde::{Deserializer, Serialize, Serializer};
41
42 pub fn serialize<S: Serializer>(pooling: &Pooling, serializer: S) -> Result<S::Ok, S::Error> {
43 if serializer.is_human_readable() {
44 let name = match pooling {
45 Pooling::Never => "never",
46 Pooling::IfAvailable => "ifAvailable",
47 Pooling::Standard => "standard",
48 };
49 serializer.serialize_str(name)
50 } else {
51 (*pooling as u8).serialize(serializer)
52 }
53 }
54
55 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Pooling, D::Error> {
63 struct PoolingVisitor;
64
65 impl<'de> serde::de::Visitor<'de> for PoolingVisitor {
66 type Value = Pooling;
67
68 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
69 f.write_str("a Pooling variant: 'never'/'ifAvailable'/'standard' or 0/1/2")
70 }
71
72 fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Pooling, E> {
73 match v {
74 "never" | "Never" => Ok(Pooling::Never),
75 "ifAvailable" | "IfAvailable" | "ifavailable" => Ok(Pooling::IfAvailable),
76 "standard" | "Standard" => Ok(Pooling::Standard),
77 other => Err(E::custom(format!(
78 "unknown pooling variant '{}', expected 'never' | 'ifAvailable' | 'standard'",
79 other
80 ))),
81 }
82 }
83
84 fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Pooling, E> {
85 self.visit_str(&v)
86 }
87
88 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Pooling, E> {
89 match v {
90 0 => Ok(Pooling::Never),
91 1 => Ok(Pooling::IfAvailable),
92 2 => Ok(Pooling::Standard),
93 other => Err(E::custom(format!("unknown pooling discriminant {}", other))),
94 }
95 }
96
97 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Pooling, E> {
98 if v < 0 {
99 return Err(E::custom(format!("negative pooling discriminant {}", v)));
100 }
101 self.visit_u64(v as u64)
102 }
103
104 fn visit_u8<E: serde::de::Error>(self, v: u8) -> Result<Pooling, E> {
105 self.visit_u64(v as u64)
106 }
107 }
108
109 if deserializer.is_human_readable() {
110 deserializer.deserialize_any(PoolingVisitor)
111 } else {
112 deserializer.deserialize_u8(PoolingVisitor)
113 }
114 }
115
116 #[cfg(test)]
117 mod tests {
118 use super::*;
119 use serde::{Deserialize, Serialize};
120
121 #[derive(Serialize, Deserialize, PartialEq, Debug)]
122 struct Wrap(#[serde(with = "super")] Pooling);
123
124 #[test]
125 fn json_emits_camelcase_string() {
126 for (variant, expected) in [
127 (Pooling::Never, "\"never\""),
128 (Pooling::IfAvailable, "\"ifAvailable\""),
129 (Pooling::Standard, "\"standard\""),
130 ] {
131 let json = serde_json::to_string(&Wrap(variant)).expect("serialize");
132 assert_eq!(json, expected);
133 let restored: Wrap = serde_json::from_str(expected).expect("deserialize");
134 assert_eq!(restored, Wrap(variant));
135 }
136 }
137
138 #[test]
139 fn bincode_keeps_u8_discriminant() {
140 for (variant, expected_u8) in [
141 (Pooling::Never, 0),
142 (Pooling::IfAvailable, 1),
143 (Pooling::Standard, 2),
144 ] {
145 let bytes =
146 bincode::serde::encode_to_vec(Wrap(variant), bincode::config::standard())
147 .expect("bincode encode");
148 assert_eq!(bytes.last(), Some(&expected_u8));
149 let (restored, _): (Wrap, usize) =
150 bincode::serde::decode_from_slice(&bytes, bincode::config::standard())
151 .expect("bincode decode");
152 assert_eq!(restored, Wrap(variant));
153 }
154 }
155 }
156}