amaru_kernel/cardano/
certificate_pointer.rs1use std::fmt;
16
17use crate::{Slot, TransactionPointer, cbor};
18
19#[derive(Debug, Copy, Clone, PartialEq, Eq, Default, PartialOrd)]
20pub struct CertificatePointer {
21 pub transaction: TransactionPointer,
22 pub certificate_index: usize,
23}
24
25impl CertificatePointer {
26 pub fn slot(&self) -> Slot {
27 self.transaction.slot
28 }
29}
30
31impl fmt::Display for CertificatePointer {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{},certificate={}", &self.transaction, &self.certificate_index)
34 }
35}
36
37impl<C> cbor::encode::Encode<C> for CertificatePointer {
38 fn encode<W: cbor::encode::Write>(
39 &self,
40 e: &mut cbor::Encoder<W>,
41 ctx: &mut C,
42 ) -> Result<(), cbor::encode::Error<W::Error>> {
43 e.array(2)?;
44 e.encode_with(self.transaction, ctx)?;
45 e.encode_with(self.certificate_index, ctx)?;
46 Ok(())
47 }
48}
49
50impl<'b, C> cbor::decode::Decode<'b, C> for CertificatePointer {
51 fn decode(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
52 cbor::heterogeneous_array(d, |d, assert_len| {
53 assert_len(2)?;
54 Ok(CertificatePointer { transaction: d.decode_with(ctx)?, certificate_index: d.decode_with(ctx)? })
55 })
56 }
57}
58
59#[cfg(any(test, feature = "test-utils"))]
60pub use tests::*;
61
62#[cfg(any(test, feature = "test-utils"))]
63mod tests {
64 use proptest::{prelude::*, prop_compose};
65
66 use super::*;
67 use crate::{any_transaction_pointer, prop_cbor_roundtrip};
68
69 prop_cbor_roundtrip!(CertificatePointer, any_certificate_pointer(u64::MAX));
70
71 prop_compose! {
72 pub fn any_certificate_pointer(max_slot: u64)(
73 transaction in any_transaction_pointer(max_slot),
74 certificate_index in any::<usize>(),
75 ) -> CertificatePointer {
76 CertificatePointer {
77 transaction,
78 certificate_index,
79 }
80 }
81 }
82
83 #[cfg(test)]
84 mod internal {
85 use test_case::test_case;
86
87 use super::*;
88
89 #[test_case((42, 0, 0), (42, 0, 0) => with |(left, right)| assert_eq!(left, right); "reflexivity")]
90 #[test_case((42, 0, 0), (43, 0, 0) => with |(left, right)| assert!(left < right); "across slots")]
91 #[test_case((42, 0, 0), (42, 1, 0) => with |(left, right)| assert!(left < right); "across transactions")]
92 #[test_case((42, 0, 0), (42, 0, 1) => with |(left, right)| assert!(left < right); "across certificates")]
93 #[test_case((42, 0, 5), (42, 1, 0) => with |(left, right)| assert!(left < right); "across transactions and certs")]
94 fn test_pointers(
95 left: (u64, usize, usize),
96 right: (u64, usize, usize),
97 ) -> (CertificatePointer, CertificatePointer) {
98 let new_pointer = |args: (Slot, usize, usize)| CertificatePointer {
99 transaction: TransactionPointer { slot: args.0, transaction_index: args.1 },
100 certificate_index: args.2,
101 };
102
103 (new_pointer((Slot::from(left.0), left.1, left.2)), new_pointer((Slot::from(right.0), right.1, right.2)))
104 }
105 }
106}