ergo_chain_types/json/
votes.rs

1//! Code to implement `Votes` JSON encoding
2
3use std::convert::{TryFrom, TryInto};
4
5use crate::votes::{Votes, VotesError};
6use crate::Base16DecodedBytes;
7
8#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
9#[serde(untagged)]
10pub(crate) enum VotesEncodingVariants {
11    AsStr(Base16DecodedBytes),
12    /// We need `serde_json::Number` here due to a known `serde_json` bug described here:
13    /// <https://github.com/serde-rs/json/issues/740>. Basically we can't deserialise any integer
14    /// types directly within untagged enums when the `arbitrary_precision` feature is used. The
15    /// workaround is to deserialize as `serde_json::Number` first, then manually convert the type.
16    AsByteArray(Vec<serde_json::Number>), // explorer v1
17}
18
19impl TryFrom<VotesEncodingVariants> for Votes {
20    type Error = VotesError;
21
22    fn try_from(value: VotesEncodingVariants) -> Result<Self, Self::Error> {
23        match value {
24            VotesEncodingVariants::AsStr(bytes) => bytes.try_into(),
25            VotesEncodingVariants::AsByteArray(bytes) => bytes.try_into(),
26        }
27    }
28}
29
30impl TryFrom<Vec<serde_json::Number>> for Votes {
31    type Error = VotesError;
32
33    fn try_from(bytes: Vec<serde_json::Number>) -> Result<Self, Self::Error> {
34        let bytes_u8: Vec<u8> = bytes
35            .into_iter()
36            .map(|n| {
37                #[allow(clippy::unwrap_used)]
38                {
39                    n.as_u64().unwrap() as u8
40                }
41            })
42            .collect();
43        let arr: [u8; 3] = bytes_u8.as_slice().try_into()?;
44        Ok(Self(arr))
45    }
46}