dusk_cdf/element/
impls.rs

1use std::marker::PhantomData;
2use std::{io, mem};
3
4use crate::{
5    bytes, Config, DecodableElement, DecoderContext, Element, EncodableElement, EncoderContext,
6    Preamble,
7};
8
9impl Element for bool {
10    fn len(_ctx: &Config) -> usize {
11        1
12    }
13
14    fn validate(&self, _preamble: &Preamble) -> io::Result<()> {
15        Ok(())
16    }
17}
18
19impl EncodableElement for bool {
20    fn to_buffer(&self, _ctx: &mut EncoderContext, buf: &mut [u8]) {
21        buf[0] = *self as u8;
22    }
23}
24
25impl DecodableElement for bool {
26    fn try_from_buffer_in_place<'b>(
27        &mut self,
28        ctx: &DecoderContext,
29        buf: &'b [u8],
30    ) -> io::Result<()> {
31        Self::validate_buffer(ctx.config(), buf)?;
32
33        *self = buf[0] != 0;
34
35        Ok(())
36    }
37}
38
39macro_rules! impl_num {
40    ($t:ty) => {
41        impl Element for $t {
42            fn len(_ctx: &Config) -> usize {
43                mem::size_of::<$t>()
44            }
45
46            fn validate(&self, _preamble: &Preamble) -> io::Result<()> {
47                Ok(())
48            }
49        }
50
51        impl EncodableElement for $t {
52            fn to_buffer(&self, _ctx: &mut EncoderContext, buf: &mut [u8]) {
53                bytes::encode_bytes(&self.to_le_bytes(), buf);
54            }
55        }
56
57        impl DecodableElement for $t {
58            fn try_from_buffer_in_place<'b>(
59                &mut self,
60                ctx: &DecoderContext,
61                buf: &'b [u8],
62            ) -> io::Result<()> {
63                Self::validate_buffer(ctx.config(), buf)?;
64
65                const LEN: usize = mem::size_of::<$t>();
66
67                let mut slf = [0u8; LEN];
68
69                slf.copy_from_slice(&buf[..LEN]);
70
71                *self = <$t>::from_le_bytes(slf);
72
73                Ok(())
74            }
75        }
76    };
77}
78
79impl_num!(u64);
80
81// usize is implemented manually as u64 so the encoding will be platform agnostic
82impl Element for usize {
83    fn len(ctx: &Config) -> usize {
84        u64::len(ctx)
85    }
86
87    fn validate(&self, _preamble: &Preamble) -> io::Result<()> {
88        Ok(())
89    }
90}
91
92impl EncodableElement for usize {
93    fn to_buffer(&self, ctx: &mut EncoderContext, buf: &mut [u8]) {
94        (*self as u64).to_buffer(ctx, buf)
95    }
96}
97
98impl DecodableElement for usize {
99    fn try_from_buffer_in_place<'b>(
100        &mut self,
101        ctx: &DecoderContext,
102        buf: &'b [u8],
103    ) -> io::Result<()> {
104        let mut slf = 0u64;
105
106        slf.try_from_buffer_in_place(ctx, buf)?;
107
108        *self = slf as usize;
109
110        Ok(())
111    }
112}
113
114impl<T> Element for Option<T>
115where
116    T: Element,
117{
118    fn len(ctx: &Config) -> usize {
119        T::len(ctx) + 1
120    }
121
122    fn validate(&self, preamble: &Preamble) -> io::Result<()> {
123        match self {
124            Some(t) => t.validate(preamble),
125            None => Ok(()),
126        }
127    }
128}
129
130impl<T> EncodableElement for Option<T>
131where
132    T: EncodableElement,
133{
134    fn to_buffer(&self, ctx: &mut EncoderContext, buf: &mut [u8]) {
135        let buf = self.is_some().encode(ctx, buf);
136
137        // Will fill the space with zeroes, if `None`. This will guarantee deterministic
138        // serialization, which will be desirable for checksum routines.
139        match self {
140            Some(t) => t.to_buffer(ctx, buf),
141            None => buf[..Self::len(ctx.config()).saturating_sub(1)].fill(0),
142        }
143    }
144}
145
146impl<T> DecodableElement for Option<T>
147where
148    T: DecodableElement,
149{
150    fn try_from_buffer_in_place<'b>(
151        &mut self,
152        ctx: &DecoderContext,
153        buf: &'b [u8],
154    ) -> io::Result<()> {
155        Self::validate_buffer(ctx.config(), buf)?;
156
157        let (is_some, buf) = bool::try_decode(ctx, buf)?;
158        match self {
159            Some(t) if is_some => {
160                t.try_from_buffer_in_place(ctx, buf)?;
161            }
162
163            None if is_some => {
164                let t = T::try_from_buffer(ctx, buf)?;
165
166                self.replace(t);
167            }
168
169            Some(_) | None => {
170                self.take();
171            }
172        }
173
174        Ok(())
175    }
176}
177
178impl Element for () {
179    fn len(_ctx: &Config) -> usize {
180        0
181    }
182
183    fn validate(&self, _preamble: &Preamble) -> io::Result<()> {
184        Ok(())
185    }
186}
187
188impl EncodableElement for () {
189    fn to_buffer(&self, _ctx: &mut EncoderContext, _buf: &mut [u8]) {}
190}
191
192impl DecodableElement for () {
193    fn try_from_buffer_in_place<'b>(
194        &mut self,
195        _ctx: &DecoderContext,
196        _buf: &'b [u8],
197    ) -> io::Result<()> {
198        Ok(())
199    }
200}
201
202impl<T> Element for PhantomData<T> {
203    fn len(_ctx: &Config) -> usize {
204        0
205    }
206
207    fn validate(&self, _preamble: &Preamble) -> io::Result<()> {
208        Ok(())
209    }
210}
211
212impl<T> EncodableElement for PhantomData<T> {
213    fn to_buffer(&self, _ctx: &mut EncoderContext, _buf: &mut [u8]) {}
214}
215
216impl<T> DecodableElement for PhantomData<T> {
217    fn try_from_buffer_in_place<'b>(
218        &mut self,
219        _ctx: &DecoderContext,
220        _buf: &'b [u8],
221    ) -> io::Result<()> {
222        Ok(())
223    }
224}