From 7f3297c8a2e56d7f6d5c34da00c21410a52ae700 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Sun, 14 Jul 2024 20:52:38 -0400 Subject: [PATCH] misc: add `Distribution` --- rpc/types/src/bin.rs | 2 +- rpc/types/src/json.rs | 4 +- rpc/types/src/misc/distribution.rs | 246 +++++++++++++++++++++++++++++ rpc/types/src/misc/mod.rs | 2 + rpc/types/src/other.rs | 8 +- 5 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 rpc/types/src/misc/distribution.rs diff --git a/rpc/types/src/bin.rs b/rpc/types/src/bin.rs index 3b4e37f..8934940 100644 --- a/rpc/types/src/bin.rs +++ b/rpc/types/src/bin.rs @@ -30,7 +30,7 @@ use crate::{ }, }; -//---------------------------------------------------------------------------------------------------- TODO +//---------------------------------------------------------------------------------------------------- Definitions define_request_and_response! { get_blocks_by_heightbin, cc73fe71162d564ffda8e549b79a350bca53c454 => diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index 2bfb077..541acef 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -14,7 +14,7 @@ use crate::{ }, }; -//---------------------------------------------------------------------------------------------------- Struct definitions +//---------------------------------------------------------------------------------------------------- Definitions // This generates 2 structs: // // - `GetBlockTemplateRequest` @@ -291,7 +291,7 @@ define_request_and_response! { AccessResponseBase { blob: String, block_header: BlockHeader, - json: String, // TODO: this should be defined in a struct, it has many fields. + json: String, // FIXME: this should be defined in a struct, it has many fields. miner_tx_hash: String, tx_hashes: Vec, } diff --git a/rpc/types/src/misc/distribution.rs b/rpc/types/src/misc/distribution.rs new file mode 100644 index 0000000..0a0c675 --- /dev/null +++ b/rpc/types/src/misc/distribution.rs @@ -0,0 +1,246 @@ +//! TODO + +//---------------------------------------------------------------------------------------------------- Use +#[cfg(feature = "serde")] +use crate::serde::{serde_false, serde_true}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "epee")] +use cuprate_epee_encoding::{ + epee_object, error, + macros::bytes::{Buf, BufMut}, + read_epee_value, write_field, EpeeObject, EpeeObjectBuilder, EpeeValue, Marker, +}; + +use super::OutputDistributionData; + +//---------------------------------------------------------------------------------------------------- Free +/// TODO +#[doc = crate::macros::monero_definition_link!( + cc73fe71162d564ffda8e549b79a350bca53c454, + "rpc/core_rpc_server_commands_defs.h", + 45..=55 +)] +pub fn compress_integer_array(array: Vec) -> Vec { + todo!(); +} + +/// TODO +#[doc = crate::macros::monero_definition_link!( + cc73fe71162d564ffda8e549b79a350bca53c454, + "rpc/core_rpc_server_commands_defs.h", + 57..=72 +)] +pub fn decompress_integer_array(array: Vec) -> Vec { + todo!(); +} + +//---------------------------------------------------------------------------------------------------- Distribution +#[doc = crate::macros::monero_definition_link!( + cc73fe71162d564ffda8e549b79a350bca53c454, + "rpc/core_rpc_server_commands_defs.h", + 2468..=2508 +)] +/// Used in [`crate::json::GetOutputDistributionResponse`]. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(untagged))] +pub enum Distribution { + /// TODO + Json { + data: OutputDistributionData, + amount: u64, + #[cfg_attr(feature = "serde", serde(serialize_with = "serde_false"))] + /// Will always be serialized as `false`. + binary: bool, + #[cfg_attr(feature = "serde", serde(serialize_with = "serde_false"))] + /// Will always be serialized as `false`. + compress: bool, + }, + /// TODO + Binary { + data: OutputDistributionData, + amount: u64, + #[cfg_attr(feature = "serde", serde(serialize_with = "serde_true"))] + /// Will always be serialized as `true`. + binary: bool, + #[cfg_attr(feature = "serde", serde(serialize_with = "serde_false"))] + /// Will always be serialized as `false`. + compress: bool, + }, + /// TODO + CompressedBinary { + data: OutputDistributionData, + amount: u64, + compressed_data: String, + #[cfg_attr(feature = "serde", serde(serialize_with = "serde_true"))] + /// Will always be serialized as `true`. + binary: bool, + #[cfg_attr(feature = "serde", serde(serialize_with = "serde_true"))] + /// Will always be serialized as `true`. + compress: bool, + }, +} + +impl Default for Distribution { + fn default() -> Self { + Self::Json { + data: OutputDistributionData::default(), + amount: u64::default(), + binary: false, + compress: false, + } + } +} + +//---------------------------------------------------------------------------------------------------- Epee +#[cfg(feature = "epee")] +/// [`EpeeObjectBuilder`] for [`Distribution`]. +/// +/// Not for public usage. +#[allow(dead_code, missing_docs)] +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct __DistributionEpeeBuilder { + pub data: Option, + pub amount: Option, + pub compressed_data: Option, + pub binary: Option, + pub compress: Option, +} + +#[cfg(feature = "epee")] +impl EpeeObjectBuilder for __DistributionEpeeBuilder { + fn add_field(&mut self, name: &str, r: &mut B) -> error::Result { + macro_rules! read_epee_field { + ($($field:ident),*) => { + match name { + $( + stringify!($field) => { self.$field = Some(read_epee_value(r)?); }, + )* + _ => return Ok(false), + } + }; + } + + read_epee_field! { + data, + amount, + compressed_data, + binary, + compress + } + + Ok(true) + } + + fn finish(self) -> error::Result { + const ELSE: error::Error = error::Error::Format("Required field was not found!"); + + let data = self.data.ok_or(ELSE)?; + let amount = self.amount.ok_or(ELSE)?; + let binary = self.binary.ok_or(ELSE)?; + let compress = self.compress.ok_or(ELSE)?; + + let distribution = if binary && compress { + Distribution::CompressedBinary { + compressed_data: self.compressed_data.ok_or(ELSE)?, + data, + amount, + binary, + compress, + } + } else if binary { + Distribution::Binary { + data, + amount, + binary, + compress, + } + } else { + Distribution::Json { + data, + amount, + binary, + compress, + } + }; + + Ok(distribution) + } +} + +#[cfg(feature = "epee")] +impl EpeeObject for Distribution { + type Builder = __DistributionEpeeBuilder; + + fn number_of_fields(&self) -> u64 { + match self { + Self::Json { .. } => 4, + Self::Binary { .. } => 4, + Self::CompressedBinary { .. } => 5, + } + } + + fn write_fields(self, w: &mut B) -> error::Result<()> { + match self { + Self::Json { + data, + amount, + binary, + compress, + } + | Self::Binary { + data, + amount, + binary, + compress, + } => { + if amount.should_write() { + write_field(amount, "amount", w)?; + } + if binary.should_write() { + write_field(binary, "binary", w)?; + } + if compress.should_write() { + write_field(compress, "compress", w)?; + } + data.write(w)?; + } + + Self::CompressedBinary { + data, + amount, + compressed_data, + binary, + compress, + } => { + if amount.should_write() { + write_field(amount, "amount", w)?; + } + if binary.should_write() { + write_field(binary, "binary", w)?; + } + if compress.should_write() { + write_field(compress, "compress", w)?; + } + if data.start_height.should_write() { + write_field(data.start_height, "start_height", w)?; + } + if data.base.should_write() { + write_field(data.base, "base", w)?; + } + + // + // TODO: cast `String` -> `Vec` + let compressed_data = compress_integer_array(compressed_data); + if compressed_data.should_write() { + compressed_data.write(w)?; + } + } + } + + Ok(()) + } +} diff --git a/rpc/types/src/misc/mod.rs b/rpc/types/src/misc/mod.rs index 2a55646..6705ac0 100644 --- a/rpc/types/src/misc/mod.rs +++ b/rpc/types/src/misc/mod.rs @@ -13,6 +13,7 @@ //---------------------------------------------------------------------------------------------------- Mod mod binary_string; +mod distribution; mod key_image_spent_status; mod misc; mod pool_info_extent; @@ -20,6 +21,7 @@ mod status; mod tx_entry; pub use binary_string::BinaryString; +pub use distribution::Distribution; pub use key_image_spent_status::KeyImageSpentStatus; pub use misc::{ AuxPow, BlockHeader, BlockOutputIndices, ChainInfo, ConnectionInfo, GetBan, diff --git a/rpc/types/src/other.rs b/rpc/types/src/other.rs index a4d3e94..c944c87 100644 --- a/rpc/types/src/other.rs +++ b/rpc/types/src/other.rs @@ -8,12 +8,12 @@ use crate::{ defaults::{default_false, default_string, default_true}, macros::define_request_and_response, misc::{ - GetOutputsOut, OutKey, Peer, PublicNode, SpentKeyImageInfo, Status, TxEntry, TxInfo, - TxpoolStats, + GetOutputsOut, KeyImageSpentStatus, OutKey, Peer, PublicNode, SpentKeyImageInfo, Status, + TxEntry, TxInfo, TxpoolStats, }, }; -//---------------------------------------------------------------------------------------------------- TODO +//---------------------------------------------------------------------------------------------------- Definitions define_request_and_response! { get_height, cc73fe71162d564ffda8e549b79a350bca53c454 => @@ -68,7 +68,7 @@ define_request_and_response! { key_images: Vec, }, AccessResponseBase { - spent_status: Vec, // TODO: should be `KeyImageSpentStatus`. + spent_status: Vec, } }