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
13pub struct Init;
15
16pub struct SetBody;
18
19pub struct SetPrivateOptions;
21
22pub struct SetPublicOptions;
24
25pub struct Sign;
27
28pub trait EncodeEncrypted {
30 fn encode<B: MutableData>(
31 &self,
32 buf: B,
33 secret_key: Option<&SecretKey>,
34 ) -> Result<usize, Error>;
35}
36
37pub struct Builder<S, T: MutableData> {
40 buf: T,
42 n: usize,
44 c: usize,
46
47 _s: PhantomData<S>,
48}
49
50impl<S, T: MutableData> Builder<S, T> {
52 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 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 pub fn new(buf: T) -> Self {
70 Builder {
71 buf,
72 n: 0,
73 c: 0,
74 _s: PhantomData,
75 }
76 }
77
78 pub fn header(mut self, header: &Header) -> Self {
81 self.header_mut().encode(header);
82 self
83 }
84
85 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 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 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 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 pub fn sign(mut self, signing_key: &PrivateKey) -> Result<Container<T>, Error> {
167 let b = self.buf.as_mut();
168
169 let sig = crypto::pk_sign(signing_key, &b[..self.n]).unwrap();
171
172 &b[self.n..self.n + SIGNATURE_LEN].copy_from_slice(&sig);
174 self.n += SIGNATURE_LEN;
175
176 Ok(Container {
178 buff: self.buf,
179 len: self.n,
180 })
181 }
182}
183
184impl<T: ImmutableData> EncodeEncrypted for NewBody<T> {
185 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 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 let mut n = Options::encode_vec(opts.as_ref(), buf.as_mut())?;
230
231 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 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}