1use core::{marker::PhantomData, ops::Range};
2
3use crate::{
4 BuildError, ChannelId, Fcf, FloodHops, MicSize, NodeHint, OptionNumber, PacketType, PublicKey,
5 Scf, SecInfo, UnsealedPacket, options::OptionEncoder,
6};
7
8pub mod state {
10 pub struct NeedsSource;
12 pub struct NeedsCounter;
14 pub struct Configuring;
16 pub struct Complete;
18}
19
20pub struct PacketBuilder<'a> {
25 buf: &'a mut [u8],
26}
27
28impl<'a> PacketBuilder<'a> {
29 pub fn new(buf: &'a mut [u8]) -> Self {
31 Self { buf }
32 }
33
34 pub fn broadcast(self) -> BroadcastBuilder<'a, state::NeedsSource> {
36 Builder::new(self.buf, PacketType::Broadcast)
37 }
38
39 pub fn mac_ack(self, dst: NodeHint, ack_tag: [u8; 8]) -> MacAckBuilder<'a, state::Configuring> {
41 let mut builder = Builder::new(self.buf, PacketType::MacAck);
42 builder.ack_dst = Some(dst);
43 builder.ack_tag = Some(ack_tag);
44 builder
45 }
46
47 pub fn unicast(self, dst: NodeHint) -> UnicastBuilder<'a, state::NeedsSource> {
49 let mut builder = Builder::new(self.buf, PacketType::Unicast);
50 builder.dst = Some(dst);
51 builder
52 }
53
54 pub fn multicast(self, channel: ChannelId) -> MulticastBuilder<'a, state::NeedsSource> {
56 let mut builder = Builder::new(self.buf, PacketType::Multicast);
57 builder.channel = Some(channel);
58 builder
59 }
60
61 pub fn blind_unicast(
63 self,
64 channel: ChannelId,
65 dst: NodeHint,
66 ) -> BlindUnicastBuilder<'a, state::NeedsSource> {
67 let mut builder = Builder::new(self.buf, PacketType::BlindUnicast);
68 builder.channel = Some(channel);
69 builder.dst = Some(dst);
70 builder
71 }
72}
73
74pub type BroadcastBuilder<'a, S> = Builder<'a, BroadcastKind, S>;
76pub type MacAckBuilder<'a, S> = Builder<'a, MacAckKind, S>;
78pub type UnicastBuilder<'a, S> = Builder<'a, UnicastKind, S>;
80pub type MulticastBuilder<'a, S> = Builder<'a, MulticastKind, S>;
82pub type BlindUnicastBuilder<'a, S> = Builder<'a, BlindUnicastKind, S>;
84
85pub struct BroadcastKind;
87pub struct MacAckKind;
89pub struct UnicastKind;
91pub struct MulticastKind;
93pub struct BlindUnicastKind;
95
96enum SourceValue {
97 Hint(NodeHint),
98 Full(PublicKey),
99}
100
101pub struct Builder<'a, K, S> {
103 buf: &'a mut [u8],
104 packet_type: PacketType,
105 options_len: usize,
106 options_scratch: Option<Range<usize>>,
107 last_option_number: Option<u16>,
108 option_error: Option<BuildError>,
109 source: Option<SourceValue>,
110 dst: Option<NodeHint>,
111 channel: Option<ChannelId>,
112 ack_dst: Option<NodeHint>,
113 ack_tag: Option<[u8; 8]>,
114 frame_counter: Option<u32>,
115 encrypted: bool,
116 mic_size: MicSize,
117 salt: Option<u16>,
118 flood_hops: Option<FloodHops>,
119 payload: Option<Range<usize>>,
120 blind_addr: Option<Range<usize>>,
121 _marker: PhantomData<(K, S)>,
122}
123
124impl<'a, K, S> Builder<'a, K, S> {
125 fn new(buf: &'a mut [u8], packet_type: PacketType) -> Self {
126 Self {
127 buf,
128 packet_type,
129 options_len: 0,
130 options_scratch: None,
131 last_option_number: None,
132 option_error: None,
133 source: None,
134 dst: None,
135 channel: None,
136 ack_dst: None,
137 ack_tag: None,
138 frame_counter: None,
139 encrypted: matches!(
140 packet_type,
141 PacketType::BlindUnicast | PacketType::BlindUnicastAckReq
142 ),
143 mic_size: MicSize::Mic16,
144 salt: None,
145 flood_hops: None,
146 payload: None,
147 blind_addr: None,
148 _marker: PhantomData,
149 }
150 }
151
152 fn with_state<NS>(self) -> Builder<'a, K, NS> {
153 Builder {
154 buf: self.buf,
155 packet_type: self.packet_type,
156 options_len: self.options_len,
157 options_scratch: self.options_scratch,
158 last_option_number: self.last_option_number,
159 option_error: self.option_error,
160 source: self.source,
161 dst: self.dst,
162 channel: self.channel,
163 ack_dst: self.ack_dst,
164 ack_tag: self.ack_tag,
165 frame_counter: self.frame_counter,
166 encrypted: self.encrypted,
167 mic_size: self.mic_size,
168 salt: self.salt,
169 flood_hops: self.flood_hops,
170 payload: self.payload,
171 blind_addr: self.blind_addr,
172 _marker: PhantomData,
173 }
174 }
175
176 fn push_option(&mut self, number: u16, value: &[u8]) {
177 if self.option_error.is_some() {
178 return;
179 }
180 if let Some(last) = self.last_option_number {
181 if number < last {
182 self.option_error = Some(BuildError::OptionOutOfOrder);
183 return;
184 }
185 }
186 let mut live = match self.last_option_number {
187 Some(last_number) => {
188 OptionEncoder::with_last_number(&mut self.buf[1 + self.options_len..], last_number)
189 }
190 None => OptionEncoder::new(&mut self.buf[1 + self.options_len..]),
191 };
192 match live.put(number, value) {
193 Ok(()) => {
194 self.options_len += live.finish();
195 self.last_option_number = Some(number);
196 }
197 Err(err) => self.option_error = Some(err.into()),
198 }
199 }
200
201 fn stash_options(&mut self) -> Result<(), BuildError> {
204 if self.options_len == 0 {
205 return Ok(());
206 }
207 let payload_len = self
208 .payload
209 .as_ref()
210 .map(|p| p.end - p.start)
211 .unwrap_or(0);
212 let scratch_end = self
213 .buf
214 .len()
215 .checked_sub(payload_len)
216 .ok_or(BuildError::BufferTooSmall)?;
217 let scratch_start = scratch_end
218 .checked_sub(self.options_len)
219 .ok_or(BuildError::BufferTooSmall)?;
220 if scratch_start < 1 + self.options_len {
221 return Err(BuildError::BufferTooSmall);
222 }
223 self.buf.copy_within(1..1 + self.options_len, scratch_start);
224 self.options_scratch = Some(scratch_start..scratch_end);
225 Ok(())
226 }
227
228 fn emit_options(
231 &mut self,
232 cursor: &mut usize,
233 has_payload: bool,
234 ) -> Result<Range<usize>, BuildError> {
235 let start = *cursor;
236 if let Some(scratch) = self.options_scratch.clone() {
237 let len = scratch.end - scratch.start;
238 let end = start
239 .checked_add(len)
240 .ok_or(BuildError::BufferTooSmall)?;
241 if end > self.buf.len() {
242 return Err(BuildError::BufferTooSmall);
243 }
244 self.buf.copy_within(scratch, start);
245 *cursor = end;
246 }
247 if has_payload {
248 let marker_slot = *cursor;
249 if marker_slot >= self.buf.len() {
250 return Err(BuildError::BufferTooSmall);
251 }
252 self.buf[marker_slot] = 0xFF;
253 *cursor = marker_slot + 1;
254 }
255 Ok(start..*cursor)
256 }
257
258 fn write_common_prefix(&mut self) -> Result<usize, BuildError> {
259 if let Some(err) = self.option_error {
260 return Err(err);
261 }
262 self.stash_options()?;
263 let full_source = matches!(self.source, Some(SourceValue::Full(_)));
264 let fcf = Fcf::new(self.packet_type, full_source, self.flood_hops.is_some());
265 if self.buf.is_empty() {
266 return Err(BuildError::BufferTooSmall);
267 }
268 self.buf[0] = fcf.0;
269 let mut cursor = 1;
270 if let Some(fhops) = self.flood_hops {
271 self.buf
272 .get_mut(cursor)
273 .ok_or(BuildError::BufferTooSmall)
274 .map(|slot| *slot = fhops.0)?;
275 cursor += 1;
276 }
277 Ok(cursor)
278 }
279
280 fn write_source(&mut self, cursor: &mut usize) -> Result<(), BuildError> {
281 match self.source {
282 Some(SourceValue::Hint(hint)) => {
283 let end = *cursor + 3;
284 self.buf
285 .get_mut(*cursor..end)
286 .ok_or(BuildError::BufferTooSmall)?
287 .copy_from_slice(&hint.0);
288 *cursor = end;
289 }
290 Some(SourceValue::Full(key)) => {
291 let end = *cursor + 32;
292 self.buf
293 .get_mut(*cursor..end)
294 .ok_or(BuildError::BufferTooSmall)?
295 .copy_from_slice(&key.0);
296 *cursor = end;
297 }
298 None => return Err(BuildError::MissingSource),
299 }
300 Ok(())
301 }
302
303 fn stage_payload(&mut self, data: &[u8]) {
304 let scratch_start = match self.buf.len().checked_sub(data.len()) {
305 Some(value) => value,
306 None => {
307 self.option_error = Some(BuildError::BufferTooSmall);
308 return;
309 }
310 };
311 if let Some(slot) = self.buf.get_mut(scratch_start..scratch_start + data.len()) {
312 slot.copy_from_slice(data);
313 self.payload = Some(scratch_start..scratch_start + data.len());
314 } else {
315 self.option_error = Some(BuildError::BufferTooSmall);
316 }
317 }
318
319 fn copy_staged_payload(&mut self, cursor: &mut usize) -> Result<Range<usize>, BuildError> {
320 let payload = self.payload.clone().ok_or(BuildError::MissingPayload)?;
321 let len = payload.end - payload.start;
322 let start = *cursor;
323 let end = start + len;
324 if end > self.buf.len() {
325 return Err(BuildError::BufferTooSmall);
326 }
327 self.buf.copy_within(payload, start);
328 *cursor = end;
329 Ok(start..end)
330 }
331
332 fn stage_blind_addr(&mut self, cursor: &mut usize) -> Result<Range<usize>, BuildError> {
333 let dst = self.dst.ok_or(BuildError::MissingDestination)?;
334 let start = *cursor;
335 let dst_end = start + 3;
336 self.buf
337 .get_mut(start..dst_end)
338 .ok_or(BuildError::BufferTooSmall)?
339 .copy_from_slice(&dst.0);
340 *cursor = dst_end;
341 self.write_source(cursor)?;
342 let end = *cursor;
343 Ok(start..end)
344 }
345}
346
347impl<'a> BroadcastBuilder<'a, state::NeedsSource> {
348 pub fn source_hint(mut self, hint: NodeHint) -> BroadcastBuilder<'a, state::Configuring> {
350 self.source = Some(SourceValue::Hint(hint));
351 self.with_state()
352 }
353
354 pub fn source_full(mut self, key: &PublicKey) -> BroadcastBuilder<'a, state::Configuring> {
356 self.source = Some(SourceValue::Full(*key));
357 self.with_state()
358 }
359}
360
361impl<'a> UnicastBuilder<'a, state::NeedsSource> {
362 pub fn source_hint(mut self, hint: NodeHint) -> UnicastBuilder<'a, state::NeedsCounter> {
364 self.source = Some(SourceValue::Hint(hint));
365 self.with_state()
366 }
367
368 pub fn source_full(mut self, key: &PublicKey) -> UnicastBuilder<'a, state::NeedsCounter> {
370 self.source = Some(SourceValue::Full(*key));
371 self.with_state()
372 }
373}
374
375impl<'a> MulticastBuilder<'a, state::NeedsSource> {
376 pub fn source_hint(mut self, hint: NodeHint) -> MulticastBuilder<'a, state::NeedsCounter> {
378 self.source = Some(SourceValue::Hint(hint));
379 self.with_state()
380 }
381
382 pub fn source_full(mut self, key: &PublicKey) -> MulticastBuilder<'a, state::NeedsCounter> {
384 self.source = Some(SourceValue::Full(*key));
385 self.with_state()
386 }
387}
388
389impl<'a> BlindUnicastBuilder<'a, state::NeedsSource> {
390 pub fn source_hint(mut self, hint: NodeHint) -> BlindUnicastBuilder<'a, state::NeedsCounter> {
392 self.source = Some(SourceValue::Hint(hint));
393 self.with_state()
394 }
395
396 pub fn source_full(mut self, key: &PublicKey) -> BlindUnicastBuilder<'a, state::NeedsCounter> {
398 self.source = Some(SourceValue::Full(*key));
399 self.with_state()
400 }
401}
402
403impl<'a> UnicastBuilder<'a, state::NeedsCounter> {
404 pub fn frame_counter(mut self, counter: u32) -> UnicastBuilder<'a, state::Configuring> {
406 self.frame_counter = Some(counter);
407 self.with_state()
408 }
409}
410
411impl<'a> MulticastBuilder<'a, state::NeedsCounter> {
412 pub fn frame_counter(mut self, counter: u32) -> MulticastBuilder<'a, state::Configuring> {
414 self.frame_counter = Some(counter);
415 self.with_state()
416 }
417}
418
419impl<'a> BlindUnicastBuilder<'a, state::NeedsCounter> {
420 pub fn frame_counter(mut self, counter: u32) -> BlindUnicastBuilder<'a, state::Configuring> {
422 self.frame_counter = Some(counter);
423 self.with_state()
424 }
425}
426
427macro_rules! impl_configuring_common {
428 ($name:ident<$state:ty>) => {
429 impl<'a> $name<'a, $state> {
430 pub fn flood_hops(mut self, remaining: u8) -> Self {
432 if let Some(value) = FloodHops::new(remaining, 0) {
433 self.flood_hops = Some(value);
434 }
435 self
436 }
437
438 pub fn region_code(mut self, code: [u8; 2]) -> Self {
440 self.push_option(OptionNumber::RegionCode.as_u16(), &code);
441 self
442 }
443
444 pub fn trace_route(mut self) -> Self {
446 self.push_option(OptionNumber::TraceRoute.as_u16(), &[]);
447 self
448 }
449
450 pub fn source_route(mut self, hops: &[crate::RouterHint]) -> Self {
452 let mut encoded = [0u8; 30];
453 let needed = hops.len() * 2;
454 if needed > encoded.len() {
455 self.option_error = Some(BuildError::BufferTooSmall);
456 return self;
457 }
458 for (index, hop) in hops.iter().enumerate() {
459 encoded[index * 2..index * 2 + 2].copy_from_slice(&hop.0);
460 }
461 self.push_option(OptionNumber::SourceRoute.as_u16(), &encoded[..needed]);
462 self
463 }
464
465 pub fn option(mut self, number: OptionNumber, value: &[u8]) -> Self {
467 self.push_option(number.as_u16(), value);
468 self
469 }
470 }
471 };
472}
473
474impl_configuring_common!(BroadcastBuilder<state::Configuring>);
475impl_configuring_common!(MacAckBuilder<state::Configuring>);
476impl_configuring_common!(UnicastBuilder<state::Configuring>);
477impl_configuring_common!(MulticastBuilder<state::Configuring>);
478impl_configuring_common!(BlindUnicastBuilder<state::Configuring>);
479
480impl<'a> UnicastBuilder<'a, state::Configuring> {
481 pub fn ack_requested(mut self) -> Self {
483 self.packet_type = PacketType::UnicastAckReq;
484 self
485 }
486
487 pub fn encrypted(mut self) -> Self {
489 self.encrypted = true;
490 self
491 }
492
493 pub fn mic_size(mut self, size: MicSize) -> Self {
495 self.mic_size = size;
496 self
497 }
498
499 pub fn salt(mut self, salt: u16) -> Self {
501 self.salt = Some(salt);
502 self
503 }
504
505 pub fn payload(mut self, data: &[u8]) -> UnicastBuilder<'a, state::Complete> {
507 self.stage_payload(data);
508 self.with_state()
509 }
510}
511
512impl<'a> MulticastBuilder<'a, state::Configuring> {
513 pub fn encrypted(mut self) -> Self {
515 self.encrypted = true;
516 self
517 }
518
519 pub fn mic_size(mut self, size: MicSize) -> Self {
521 self.mic_size = size;
522 self
523 }
524
525 pub fn salt(mut self, salt: u16) -> Self {
527 self.salt = Some(salt);
528 self
529 }
530
531 pub fn payload(mut self, data: &[u8]) -> MulticastBuilder<'a, state::Complete> {
533 self.stage_payload(data);
534 self.with_state()
535 }
536}
537
538impl<'a> BlindUnicastBuilder<'a, state::Configuring> {
539 pub fn ack_requested(mut self) -> Self {
541 self.packet_type = PacketType::BlindUnicastAckReq;
542 self
543 }
544
545 pub fn encrypted(mut self) -> Self {
547 self.encrypted = true;
548 self
549 }
550
551 pub fn unencrypted(mut self) -> Self {
557 self.encrypted = false;
558 self
559 }
560
561 pub fn mic_size(mut self, size: MicSize) -> Self {
563 self.mic_size = size;
564 self
565 }
566
567 pub fn salt(mut self, salt: u16) -> Self {
569 self.salt = Some(salt);
570 self
571 }
572
573 pub fn payload(mut self, data: &[u8]) -> BlindUnicastBuilder<'a, state::Complete> {
575 self.stage_payload(data);
576 self.with_state()
577 }
578}
579
580impl<'a> BroadcastBuilder<'a, state::Configuring> {
581 pub fn payload(mut self, data: &[u8]) -> BroadcastBuilder<'a, state::Complete> {
583 self.stage_payload(data);
584 self.with_state()
585 }
586
587 pub fn build(mut self) -> Result<&'a [u8], BuildError> {
591 let has_payload = self.payload.is_some();
592 let mut cursor = self.write_common_prefix()?;
593 self.write_source(&mut cursor)?;
594 self.emit_options(&mut cursor, has_payload)?;
595 if has_payload {
596 let _ = self.copy_staged_payload(&mut cursor)?;
597 }
598 Ok(&self.buf[..cursor])
599 }
600}
601
602impl<'a> BroadcastBuilder<'a, state::Complete> {
603 pub fn build(self) -> Result<&'a [u8], BuildError> {
605 self.with_state::<state::Configuring>().build()
606 }
607}
608
609impl<'a> MacAckBuilder<'a, state::Configuring> {
610 pub fn build(mut self) -> Result<&'a [u8], BuildError> {
615 let mut cursor = self.write_common_prefix()?;
616 let dst = self.ack_dst.ok_or(BuildError::MissingDestination)?;
617 self.buf
618 .get_mut(cursor..cursor + 3)
619 .ok_or(BuildError::BufferTooSmall)?
620 .copy_from_slice(&dst.0);
621 cursor += 3;
622 self.emit_options(&mut cursor, false)?;
623 let ack_tag = self.ack_tag.ok_or(BuildError::MissingAckTag)?;
624 self.buf
625 .get_mut(cursor..cursor + 8)
626 .ok_or(BuildError::BufferTooSmall)?
627 .copy_from_slice(&ack_tag);
628 cursor += 8;
629 Ok(&self.buf[..cursor])
630 }
631}
632
633impl<'a> UnicastBuilder<'a, state::Complete> {
634 pub fn build(self) -> Result<UnsealedPacket<'a>, BuildError> {
635 self.with_state::<state::Configuring>().build()
636 }
637}
638
639impl<'a> UnicastBuilder<'a, state::Configuring> {
640 pub fn build(mut self) -> Result<UnsealedPacket<'a>, BuildError> {
642 let has_payload = self.payload.is_some();
643 let mut cursor = self.write_common_prefix()?;
644 let dst = self.dst.ok_or(BuildError::MissingDestination)?;
645 self.buf
646 .get_mut(cursor..cursor + 3)
647 .ok_or(BuildError::BufferTooSmall)?
648 .copy_from_slice(&dst.0);
649 cursor += 3;
650 self.write_source(&mut cursor)?;
651 let scf = Scf::new(self.encrypted, self.mic_size, self.salt.is_some());
652 let sec_info = SecInfo {
653 scf,
654 frame_counter: self.frame_counter.ok_or(BuildError::MissingFrameCounter)?,
655 salt: self.salt,
656 };
657 let sec_start = cursor;
658 cursor += sec_info.encode(
659 self.buf
660 .get_mut(cursor..)
661 .ok_or(BuildError::BufferTooSmall)?,
662 )?;
663 let opts_range = self.emit_options(&mut cursor, has_payload)?;
664 let body_start = cursor;
665 let body_range = if has_payload {
666 self.copy_staged_payload(&mut cursor)?
667 } else {
668 body_start..body_start
669 };
670 let mic_start = cursor;
671 let mic_end = mic_start + self.mic_size.byte_len();
672 self.buf
673 .get_mut(mic_start..mic_end)
674 .ok_or(BuildError::BufferTooSmall)?
675 .fill(0);
676 cursor = mic_end;
677 Ok(UnsealedPacket::new(
678 self.buf,
679 cursor,
680 body_range,
681 None,
682 mic_start..mic_end,
683 sec_start..sec_start + sec_info.wire_len(),
684 opts_range,
685 ))
686 }
687}
688
689impl<'a> MulticastBuilder<'a, state::Complete> {
690 pub fn build(self) -> Result<UnsealedPacket<'a>, BuildError> {
691 self.with_state::<state::Configuring>().build()
692 }
693}
694
695impl<'a> MulticastBuilder<'a, state::Configuring> {
696 pub fn build(mut self) -> Result<UnsealedPacket<'a>, BuildError> {
699 let mut cursor = self.write_common_prefix()?;
700 let channel = self.channel.ok_or(BuildError::MissingChannel)?;
701 self.buf
702 .get_mut(cursor..cursor + 2)
703 .ok_or(BuildError::BufferTooSmall)?
704 .copy_from_slice(&channel.0);
705 cursor += 2;
706 let scf = Scf::new(self.encrypted, self.mic_size, self.salt.is_some());
707 let sec_info = SecInfo {
708 scf,
709 frame_counter: self.frame_counter.ok_or(BuildError::MissingFrameCounter)?,
710 salt: self.salt,
711 };
712 let sec_start = cursor;
713 cursor += sec_info.encode(
714 self.buf
715 .get_mut(cursor..)
716 .ok_or(BuildError::BufferTooSmall)?,
717 )?;
718 let opts_range = self.emit_options(&mut cursor, true)?;
720 let body_start = cursor;
721 self.write_source(&mut cursor)?;
722 let payload_range = self.copy_staged_payload(&mut cursor)?;
723 let body_range = if self.encrypted {
724 body_start..payload_range.end
725 } else {
726 payload_range
727 };
728 let mic_start = cursor;
729 let mic_end = mic_start + self.mic_size.byte_len();
730 self.buf
731 .get_mut(mic_start..mic_end)
732 .ok_or(BuildError::BufferTooSmall)?
733 .fill(0);
734 cursor = mic_end;
735 Ok(UnsealedPacket::new(
736 self.buf,
737 cursor,
738 body_range,
739 None,
740 mic_start..mic_end,
741 sec_start..sec_start + sec_info.wire_len(),
742 opts_range,
743 ))
744 }
745}
746
747impl<'a> BlindUnicastBuilder<'a, state::Complete> {
748 pub fn build(self) -> Result<UnsealedPacket<'a>, BuildError> {
749 self.with_state::<state::Configuring>().build()
750 }
751}
752
753impl<'a> BlindUnicastBuilder<'a, state::Configuring> {
754 pub fn build(mut self) -> Result<UnsealedPacket<'a>, BuildError> {
757 let mut cursor = self.write_common_prefix()?;
758 let channel = self.channel.ok_or(BuildError::MissingChannel)?;
759 self.buf
760 .get_mut(cursor..cursor + 2)
761 .ok_or(BuildError::BufferTooSmall)?
762 .copy_from_slice(&channel.0);
763 cursor += 2;
764 let scf = Scf::new(self.encrypted, self.mic_size, self.salt.is_some());
765 let sec_info = SecInfo {
766 scf,
767 frame_counter: self.frame_counter.ok_or(BuildError::MissingFrameCounter)?,
768 salt: self.salt,
769 };
770 let sec_start = cursor;
771 cursor += sec_info.encode(
772 self.buf
773 .get_mut(cursor..)
774 .ok_or(BuildError::BufferTooSmall)?,
775 )?;
776 let opts_range = self.emit_options(&mut cursor, true)?;
778 let blind_addr_range = self.stage_blind_addr(&mut cursor)?;
779 let body_range = self.copy_staged_payload(&mut cursor)?;
780 let mic_start = cursor;
781 let mic_end = mic_start + self.mic_size.byte_len();
782 self.buf
783 .get_mut(mic_start..mic_end)
784 .ok_or(BuildError::BufferTooSmall)?
785 .fill(0);
786 cursor = mic_end;
787 Ok(UnsealedPacket::new(
788 self.buf,
789 cursor,
790 body_range,
791 Some(blind_addr_range),
792 mic_start..mic_end,
793 sec_start..sec_start + sec_info.wire_len(),
794 opts_range,
795 ))
796 }
797}