1#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "epee")]
8use cuprate_epee_encoding::{
9 epee_object, error,
10 macros::bytes::{Buf, BufMut},
11 read_epee_value, write_field, EpeeObject, EpeeObjectBuilder, EpeeValue,
12};
13
14#[doc = crate::macros::monero_definition_link!(
19 cc73fe71162d564ffda8e549b79a350bca53c454,
20 "rpc/core_rpc_server_commands_defs.h",
21 45..=55
22)]
23#[cfg(any(feature = "epee", feature = "serde"))]
24fn compress_integer_array(_: &[u64]) -> Vec<u8> {
25 todo!()
26}
27
28#[doc = crate::macros::monero_definition_link!(
32 cc73fe71162d564ffda8e549b79a350bca53c454,
33 "rpc/core_rpc_server_commands_defs.h",
34 57..=72
35)]
36#[cfg(any(feature = "epee", feature = "serde"))]
37fn decompress_integer_array(_: &[u8]) -> Vec<u64> {
38 todo!()
39}
40
41#[doc = crate::macros::monero_definition_link!(
43 cc73fe71162d564ffda8e549b79a350bca53c454,
44 "rpc/core_rpc_server_commands_defs.h",
45 2468..=2508
46)]
47#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "serde", serde(untagged))]
66pub enum Distribution {
67 Uncompressed(DistributionUncompressed),
69 CompressedBinary(DistributionCompressedBinary),
71}
72
73impl Default for Distribution {
74 fn default() -> Self {
75 Self::Uncompressed(DistributionUncompressed::default())
76 }
77}
78
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
81#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
82pub struct DistributionUncompressed {
83 pub start_height: u64,
84 pub base: u64,
85 pub distribution: Vec<u64>,
87 pub amount: u64,
88 pub binary: bool,
89}
90
91#[cfg(feature = "epee")]
92epee_object! {
93 DistributionUncompressed,
94 start_height: u64,
95 base: u64,
96 distribution: Vec<u64>,
97 amount: u64,
98 binary: bool,
99}
100
101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
104pub struct DistributionCompressedBinary {
105 pub start_height: u64,
106 pub base: u64,
107 #[cfg_attr(
108 feature = "serde",
109 serde(serialize_with = "serialize_distribution_as_compressed_data")
110 )]
111 #[cfg_attr(
112 feature = "serde",
113 serde(deserialize_with = "deserialize_compressed_data_as_distribution")
114 )]
115 #[cfg_attr(feature = "serde", serde(rename = "compressed_data"))]
116 pub distribution: Vec<u64>,
117 pub amount: u64,
118}
119
120#[cfg(feature = "epee")]
121epee_object! {
122 DistributionCompressedBinary,
123 start_height: u64,
124 base: u64,
125 distribution: Vec<u64>,
126 amount: u64,
127}
128
129#[cfg(feature = "serde")]
134#[expect(clippy::ptr_arg)]
135fn serialize_distribution_as_compressed_data<S>(v: &Vec<u64>, s: S) -> Result<S::Ok, S::Error>
136where
137 S: serde::Serializer,
138{
139 compress_integer_array(v).serialize(s)
140}
141
142#[cfg(feature = "serde")]
147fn deserialize_compressed_data_as_distribution<'de, D>(d: D) -> Result<Vec<u64>, D::Error>
148where
149 D: serde::Deserializer<'de>,
150{
151 Vec::<u8>::deserialize(d).map(|v| decompress_integer_array(&v))
152}
153
154#[cfg(feature = "epee")]
156#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
161pub struct __DistributionEpeeBuilder {
162 pub start_height: Option<u64>,
163 pub base: Option<u64>,
164 pub distribution: Option<Vec<u64>>,
165 pub amount: Option<u64>,
166 pub compressed_data: Option<Vec<u8>>,
167 pub binary: Option<bool>,
168 pub compress: Option<bool>,
169}
170
171#[cfg(feature = "epee")]
172impl EpeeObjectBuilder<Distribution> for __DistributionEpeeBuilder {
173 fn add_field<B: Buf>(&mut self, name: &str, r: &mut B) -> error::Result<bool> {
174 macro_rules! read_epee_field {
175 ($($field:ident),*) => {
176 match name {
177 $(
178 stringify!($field) => { self.$field = Some(read_epee_value(r)?); },
179 )*
180 _ => return Ok(false),
181 }
182 };
183 }
184
185 read_epee_field! {
186 start_height,
187 base,
188 amount,
189 binary,
190 compress,
191 compressed_data,
192 distribution
193 }
194
195 Ok(true)
196 }
197
198 fn finish(self) -> error::Result<Distribution> {
199 const ELSE: error::Error = error::Error::Format("Required field was not found!");
200
201 let start_height = self.start_height.ok_or(ELSE)?;
202 let base = self.base.ok_or(ELSE)?;
203 let amount = self.amount.ok_or(ELSE)?;
204
205 let distribution = if let Some(compressed_data) = self.compressed_data {
206 let distribution = decompress_integer_array(&compressed_data);
207 Distribution::CompressedBinary(DistributionCompressedBinary {
208 start_height,
209 base,
210 distribution,
211 amount,
212 })
213 } else if let Some(distribution) = self.distribution {
214 Distribution::Uncompressed(DistributionUncompressed {
215 binary: self.binary.ok_or(ELSE)?,
216 distribution,
217 start_height,
218 base,
219 amount,
220 })
221 } else {
222 return Err(ELSE);
223 };
224
225 Ok(distribution)
226 }
227}
228
229#[cfg(feature = "epee")]
230impl EpeeObject for Distribution {
231 type Builder = __DistributionEpeeBuilder;
232
233 fn number_of_fields(&self) -> u64 {
234 match self {
235 Self::Uncompressed(s) => s.number_of_fields() + 1,
237 Self::CompressedBinary(s) => s.number_of_fields() + 2,
239 }
240 }
241
242 fn write_fields<B: BufMut>(self, w: &mut B) -> error::Result<()> {
243 match self {
244 Self::Uncompressed(s) => {
245 s.write_fields(w)?;
246 write_field(false, "compress", w)?;
247 }
248
249 Self::CompressedBinary(DistributionCompressedBinary {
250 start_height,
251 base,
252 distribution,
253 amount,
254 }) => {
255 let compressed_data = compress_integer_array(&distribution);
256
257 start_height.write(w)?;
258 base.write(w)?;
259 compressed_data.write(w)?;
260 amount.write(w)?;
261
262 write_field(true, "binary", w)?;
263 write_field(true, "compress", w)?;
264 }
265 }
266
267 Ok(())
268 }
269}
270
271#[cfg(test)]
273mod tests {
274 }