casper_types/transaction/
transaction_scheduling.rs

1use super::serialization::CalltableSerializationEnvelope;
2#[cfg(any(feature = "testing", test))]
3use crate::testing::TestRng;
4use crate::{
5    bytesrepr::{
6        Error::{self, Formatting},
7        FromBytes, ToBytes,
8    },
9    transaction::serialization::CalltableSerializationEnvelopeBuilder,
10};
11use alloc::vec::Vec;
12use core::fmt::{self, Display, Formatter};
13#[cfg(feature = "datasize")]
14use datasize::DataSize;
15#[cfg(any(feature = "testing", test))]
16use rand::Rng;
17#[cfg(feature = "json-schema")]
18use schemars::JsonSchema;
19#[cfg(any(feature = "std", test))]
20use serde::{Deserialize, Serialize};
21
22/// The scheduling mode of a [`crate::Transaction`].
23#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
24#[cfg_attr(
25    any(feature = "std", test),
26    derive(Serialize, Deserialize),
27    serde(deny_unknown_fields)
28)]
29#[cfg_attr(feature = "datasize", derive(DataSize))]
30#[cfg_attr(
31    feature = "json-schema",
32    derive(JsonSchema),
33    schemars(description = "Scheduling mode of a Transaction.")
34)]
35pub enum TransactionScheduling {
36    /// No special scheduling applied.
37    Standard,
38}
39
40impl TransactionScheduling {
41    fn serialized_field_lengths(&self) -> Vec<usize> {
42        match self {
43            TransactionScheduling::Standard => {
44                vec![crate::bytesrepr::U8_SERIALIZED_LENGTH]
45            }
46        }
47    }
48
49    /// Returns a random `TransactionScheduling`.
50    #[cfg(any(feature = "testing", test))]
51    pub fn random(rng: &mut TestRng) -> Self {
52        match rng.gen_range(0..1) {
53            0 => TransactionScheduling::Standard,
54            _ => unreachable!(),
55        }
56    }
57}
58
59const TAG_FIELD_INDEX: u16 = 0;
60
61const STANDARD_VARIANT: u8 = 0;
62
63impl ToBytes for TransactionScheduling {
64    fn to_bytes(&self) -> Result<Vec<u8>, Error> {
65        match self {
66            TransactionScheduling::Standard => {
67                CalltableSerializationEnvelopeBuilder::new(self.serialized_field_lengths())?
68                    .add_field(TAG_FIELD_INDEX, &STANDARD_VARIANT)?
69                    .binary_payload_bytes()
70            }
71        }
72    }
73    fn serialized_length(&self) -> usize {
74        CalltableSerializationEnvelope::estimate_size(self.serialized_field_lengths())
75    }
76}
77
78impl FromBytes for TransactionScheduling {
79    fn from_bytes(bytes: &[u8]) -> Result<(TransactionScheduling, &[u8]), Error> {
80        let (binary_payload, remainder) = CalltableSerializationEnvelope::from_bytes(2, bytes)?;
81        let window = binary_payload.start_consuming()?.ok_or(Formatting)?;
82        window.verify_index(0)?;
83        let (tag, window) = window.deserialize_and_maybe_next::<u8>()?;
84        let to_ret = match tag {
85            STANDARD_VARIANT => {
86                if window.is_some() {
87                    return Err(Formatting);
88                }
89                Ok(TransactionScheduling::Standard)
90            }
91            _ => Err(Formatting),
92        };
93        to_ret.map(|endpoint| (endpoint, remainder))
94    }
95}
96
97impl Display for TransactionScheduling {
98    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
99        match self {
100            TransactionScheduling::Standard => write!(formatter, "schedule(standard)"),
101        }
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use crate::{bytesrepr, gens::transaction_scheduling_arb};
109    use proptest::prelude::*;
110
111    #[test]
112    fn bytesrepr_roundtrip() {
113        let rng = &mut TestRng::new();
114        for _ in 0..10 {
115            bytesrepr::test_serialization_roundtrip(&TransactionScheduling::random(rng));
116        }
117    }
118
119    proptest! {
120        #[test]
121        fn generative_bytesrepr_roundtrip(val in transaction_scheduling_arb()) {
122            bytesrepr::test_serialization_roundtrip(&val);
123        }
124    }
125}