1use alloc::vec::Vec;
20use core::fmt;
21use digest::Digest;
22use digest::typenum::U32;
23
24use crate::{BYTES_PER_LENGTH_OFFSET, Decode, DecodeError, Encode, HashTreeRoot, read_slice};
25
26#[derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
28pub enum MissingOr<T> {
29 Materialized(T),
30 Missing([u8; 32]),
31}
32
33impl<T: fmt::Debug> fmt::Debug for MissingOr<T> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Self::Materialized(t) => f.debug_tuple("Materialized").field(t).finish(),
37 Self::Missing(h) => f.debug_tuple("Missing").field(h).finish(),
38 }
39 }
40}
41
42impl<T: Clone> Clone for MissingOr<T> {
43 fn clone(&self) -> Self {
44 match self {
45 Self::Materialized(t) => Self::Materialized(t.clone()),
46 Self::Missing(h) => Self::Missing(*h),
47 }
48 }
49}
50
51impl<T: PartialEq> PartialEq for MissingOr<T> {
52 fn eq(&self, other: &Self) -> bool {
53 match (self, other) {
54 (Self::Materialized(a), Self::Materialized(b)) => a == b,
55 (Self::Missing(a), Self::Missing(b)) => a == b,
56 _ => false,
57 }
58 }
59}
60
61impl<T: Eq> Eq for MissingOr<T> {}
62
63impl<T: Encode> Encode for MissingOr<T> {
64 fn is_ssz_fixed_len() -> bool {
65 false
66 }
67 fn ssz_fixed_len() -> usize {
68 BYTES_PER_LENGTH_OFFSET
69 }
70 fn ssz_bytes_len(&self) -> usize {
71 1 + match self {
72 Self::Materialized(t) => t.ssz_bytes_len(),
73 Self::Missing(_) => 32,
74 }
75 }
76 fn ssz_append(&self, buf: &mut Vec<u8>) {
77 match self {
78 Self::Materialized(t) => {
79 buf.push(0);
80 t.ssz_append(buf);
81 }
82 Self::Missing(h) => {
83 buf.push(1);
84 buf.extend_from_slice(h);
85 }
86 }
87 }
88}
89
90impl<T: Decode> Decode for MissingOr<T> {
91 fn is_ssz_fixed_len() -> bool {
92 false
93 }
94 fn ssz_fixed_len() -> usize {
95 BYTES_PER_LENGTH_OFFSET
96 }
97 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
98 let tag = read_slice(bytes, 0, 1)?[0];
99 match tag {
100 0 => Ok(Self::Materialized(T::from_ssz_bytes(&bytes[1..])?)),
101 1 => {
102 if bytes.len() != 33 {
103 return Err(DecodeError::TrailingBytes {
104 expected: 33,
105 actual: bytes.len(),
106 });
107 }
108 let mut h = [0u8; 32];
109 h.copy_from_slice(&bytes[1..33]);
110 Ok(Self::Missing(h))
111 }
112 v => Err(DecodeError::InvalidSelector(v)),
113 }
114 }
115}
116
117impl<T: HashTreeRoot> HashTreeRoot for MissingOr<T> {
118 fn hash_tree_root<D: Digest<OutputSize = U32>>(&self) -> [u8; 32] {
119 match self {
121 Self::Materialized(t) => t.hash_tree_root::<D>(),
122 Self::Missing(h) => *h,
123 }
124 }
125}