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