dsf_core/wire/
builder.rs

1use core::marker::PhantomData;
2
3use crate::base::header::{offsets, Header, HEADER_LEN};
4use crate::base::{Encode, NewBody};
5use crate::crypto;
6use crate::error::Error;
7use crate::options::{Options, OptionsList};
8use crate::types::*;
9
10use super::container::Container;
11use super::header::WireHeader;
12
13/// Init state, no data set
14pub struct Init;
15
16/// SetBody state, has header and ID
17pub struct SetBody;
18
19/// SetPrivateOptions state, has Body and previous (SetBody)
20pub struct SetPrivateOptions;
21
22/// SetPublicOptions state, has PrivateOptions and previous (SetPrivateOptions)
23pub struct SetPublicOptions;
24
25/// Sign state, has PublicOptions and previous (SetPublicOptions)
26pub struct Sign;
27
28/// Internal trait to support encoding of optionally encrypted objects in a generic buffer
29pub trait EncodeEncrypted {
30    fn encode<B: MutableData>(
31        &self,
32        buf: B,
33        secret_key: Option<&SecretKey>,
34    ) -> Result<usize, Error>;
35}
36
37/// Builder provides a low-level wire protocol builder object.
38/// This is generic over buffer types and uses type-state mutation to ensure created objects are valid
39pub struct Builder<S, T: MutableData> {
40    /// internal data buffer
41    buf: T,
42    /// Current index count
43    n: usize,
44    /// Local index count
45    c: usize,
46
47    _s: PhantomData<S>,
48}
49
50// Implementations that are always available
51impl<S, T: MutableData> Builder<S, T> {
52    /// Set the object id
53    pub fn id(mut self, id: &Id) -> Self {
54        let d = self.buf.as_mut();
55
56        d[HEADER_LEN..HEADER_LEN + ID_LEN].clone_from_slice(id);
57
58        self
59    }
60
61    /// Fetch a mutable instance of the object header
62    pub fn header_mut(&mut self) -> WireHeader<&mut [u8]> {
63        WireHeader::new(&mut self.buf.as_mut()[..HEADER_LEN])
64    }
65}
66
67impl<T: MutableData> Builder<Init, T> {
68    /// Create a new base builder object
69    pub fn new(buf: T) -> Self {
70        Builder {
71            buf,
72            n: 0,
73            c: 0,
74            _s: PhantomData,
75        }
76    }
77
78    /// Set the object header.
79    /// Note that length fields will be overwritten by actual lengths
80    pub fn header(mut self, header: &Header) -> Self {
81        self.header_mut().encode(header);
82        self
83    }
84
85    /// Add body data, mutating the state of the builder
86    pub fn body<B: ImmutableData>(
87        mut self,
88        body: &NewBody<B>,
89        secret_key: Option<&SecretKey>,
90    ) -> Result<Builder<SetPrivateOptions, T>, Error> {
91        let b = self.buf.as_mut();
92
93        self.n = offsets::BODY;
94
95        let body_len = body.encode(&mut b[self.n..], secret_key)?;
96        self.n += body_len;
97
98        self.header_mut().set_data_len(body_len);
99
100        Ok(Builder {
101            buf: self.buf,
102            n: self.n,
103            c: 0,
104            _s: PhantomData,
105        })
106    }
107}
108
109impl<T: MutableData> Builder<SetPrivateOptions, T> {
110    /// Encode private options
111    /// This must be done in one pass as the entire options block is encrypted
112    pub fn private_options<C: AsRef<[Options]>, E: ImmutableData>(
113        mut self,
114        options: &OptionsList<C, E>,
115        secret_key: Option<&SecretKey>,
116    ) -> Result<Builder<SetPublicOptions, T>, Error> {
117        let b = self.buf.as_mut();
118
119        let n = options.encode(&mut b[self.n..], secret_key)?;
120        self.n += n;
121
122        self.header_mut().set_private_options_len(n);
123
124        Ok(Builder {
125            buf: self.buf,
126            n: self.n,
127            c: 0,
128            _s: PhantomData,
129        })
130    }
131}
132
133impl<T: MutableData> Builder<SetPublicOptions, T> {
134    /// Encode a list of public options
135    pub fn public_options<C: AsRef<[Options]>, E: ImmutableData>(
136        mut self,
137        options: &OptionsList<C, E>,
138    ) -> Result<Builder<SetPublicOptions, T>, Error> {
139        let b = self.buf.as_mut();
140
141        let n = options.encode(&mut b[self.n..], None)?;
142        self.n += n;
143        self.c += n;
144        let c = self.c;
145
146        self.header_mut().set_public_options_len(c);
147
148        Ok(self)
149    }
150
151    /// Add a single public option
152    pub fn public_option(&mut self, option: &Options) -> Result<(), Error> {
153        let b = self.buf.as_mut();
154
155        let n = option.encode(&mut b[self.n..])?;
156        self.n += n;
157        self.c += n;
158        let c = self.c;
159
160        self.header_mut().set_public_options_len(c);
161
162        Ok(())
163    }
164
165    // Sign the builder object, returning a new base object
166    pub fn sign(mut self, signing_key: &PrivateKey) -> Result<Container<T>, Error> {
167        let b = self.buf.as_mut();
168
169        // Generate signature
170        let sig = crypto::pk_sign(signing_key, &b[..self.n]).unwrap();
171
172        // Write to object
173        &b[self.n..self.n + SIGNATURE_LEN].copy_from_slice(&sig);
174        self.n += SIGNATURE_LEN;
175
176        // Return base object
177        Ok(Container {
178            buff: self.buf,
179            len: self.n,
180        })
181    }
182}
183
184impl<T: ImmutableData> EncodeEncrypted for NewBody<T> {
185    /// Encode and optionally encrypt body
186    fn encode<B: MutableData>(
187        &self,
188        mut buf: B,
189        secret_key: Option<&SecretKey>,
190    ) -> Result<usize, Error> {
191        let b = buf.as_mut();
192
193        let n = match self {
194            NewBody::Cleartext(clear) => {
195                let c = clear.as_ref();
196
197                b[..c.len()].copy_from_slice(c);
198
199                if let Some(sk) = secret_key {
200                    crypto::sk_encrypt2(sk, b, c.len()).unwrap()
201                } else {
202                    c.len()
203                }
204            }
205            NewBody::Encrypted(enc) => {
206                let e = enc.as_ref();
207
208                b[..e.len()].copy_from_slice(e);
209
210                e.len()
211            }
212            NewBody::None => 0,
213        };
214
215        Ok(n)
216    }
217}
218
219impl<C: AsRef<[Options]>, E: ImmutableData> EncodeEncrypted for OptionsList<C, E> {
220    /// Encode and optionally encrypt options
221    fn encode<B: MutableData>(
222        &self,
223        mut buf: B,
224        secret_key: Option<&SecretKey>,
225    ) -> Result<usize, Error> {
226        let n = match self {
227            OptionsList::Cleartext(opts) => {
228                // Encode options into buffer
229                let mut n = Options::encode_vec(opts.as_ref(), buf.as_mut())?;
230
231                // Encrypt if required
232                if let Some(sk) = secret_key {
233                    n = crypto::sk_encrypt2(sk, buf.as_mut(), n).unwrap();
234                }
235
236                n
237            }
238            OptionsList::Encrypted(enc) => {
239                // Write options directly to buffer
240                let b = buf.as_mut();
241                let e = enc.as_ref();
242
243                b[..e.len()].copy_from_slice(e.as_ref());
244                e.as_ref().len()
245            }
246            OptionsList::None => 0,
247        };
248
249        Ok(n)
250    }
251}