1use core::cell::Cell;
23use core::mem;
24use core::ptr;
25
26use crate::data;
27use crate::private::arena::{BuilderArena, NullArena, ReaderArena, SegmentId};
28#[cfg(feature = "alloc")]
29use crate::private::capability::ClientHook;
30use crate::private::mask::Mask;
31use crate::private::primitive::{Primitive, WireValue};
32use crate::private::units::*;
33use crate::private::zero;
34use crate::text;
35use crate::{Error, ErrorKind, MessageSize, Result};
36
37pub use self::ElementSize::{
38 Bit, Byte, EightBytes, FourBytes, InlineComposite, Pointer, TwoBytes, Void,
39};
40
41#[repr(u8)]
42#[derive(Clone, Copy, Debug, PartialEq)]
43pub enum ElementSize {
44 Void = 0,
45 Bit = 1,
46 Byte = 2,
47 TwoBytes = 3,
48 FourBytes = 4,
49 EightBytes = 5,
50 Pointer = 6,
51 InlineComposite = 7,
52}
53
54impl ElementSize {
55 fn from(val: u8) -> Self {
56 match val {
57 0 => Self::Void,
58 1 => Self::Bit,
59 2 => Self::Byte,
60 3 => Self::TwoBytes,
61 4 => Self::FourBytes,
62 5 => Self::EightBytes,
63 6 => Self::Pointer,
64 7 => Self::InlineComposite,
65 _ => panic!("illegal element size: {val}"),
66 }
67 }
68}
69
70pub fn data_bits_per_element(size: ElementSize) -> BitCount32 {
71 match size {
72 Void => 0,
73 Bit => 1,
74 Byte => 8,
75 TwoBytes => 16,
76 FourBytes => 32,
77 EightBytes => 64,
78 Pointer => 0,
79 InlineComposite => 0,
80 }
81}
82
83pub fn pointers_per_element(size: ElementSize) -> WirePointerCount32 {
84 match size {
85 Pointer => 1,
86 _ => 0,
87 }
88}
89
90#[derive(Clone, Copy, Debug)]
91pub struct StructSize {
92 pub data: WordCount16,
93 pub pointers: WirePointerCount16,
94}
95
96impl StructSize {
97 pub fn total(&self) -> WordCount32 {
98 u32::from(self.data)
99 + u32::from(self.pointers) * WordCount32::try_from(WORDS_PER_POINTER).unwrap()
100 }
101}
102
103#[repr(u8)]
104#[derive(Clone, Copy, PartialEq)]
105pub enum WirePointerKind {
106 Struct = 0,
107 List = 1,
108 Far = 2,
109 Other = 3,
110}
111
112pub enum PointerType {
113 Null,
114 Struct,
115 List,
116 Capability,
117}
118
119impl WirePointerKind {
120 fn from(val: u8) -> Self {
121 match val {
122 0 => Self::Struct,
123 1 => Self::List,
124 2 => Self::Far,
125 3 => Self::Other,
126 _ => panic!("illegal element size: {val}"),
127 }
128 }
129}
130
131#[repr(C)]
132pub(crate) struct WirePointer {
133 offset_and_kind: WireValue<u32>,
140
141 upper32bits: WireValue<u32>,
147}
148
149#[test]
150#[cfg(feature = "unaligned")]
151fn wire_pointer_align() {
152 assert_eq!(core::mem::align_of::<WirePointer>(), 1);
154}
155
156impl WirePointer {
157 #[inline]
158 pub(crate) fn kind(&self) -> WirePointerKind {
159 WirePointerKind::from((self.offset_and_kind.get() & 3) as u8)
160 }
161
162 #[inline]
163 pub(crate) fn is_positional(&self) -> bool {
164 (self.offset_and_kind.get() & 2) == 0 }
166
167 #[inline]
168 pub(crate) fn is_capability(&self) -> bool {
169 self.offset_and_kind.get() == WirePointerKind::Other as u32
170 }
171
172 #[inline]
173 #[allow(clippy::cast_possible_wrap)]
174 fn offset_in_words(&self) -> i32 {
175 1 + ((self.offset_and_kind.get() as i32) >> 2)
177 }
178
179 #[inline]
180 pub(crate) unsafe fn target(ptr: *const Self) -> *const u8 {
181 let this_addr: *const u8 = ptr as *const _;
182 unsafe { this_addr.offset(8 * (*ptr).offset_in_words() as isize) }
183 }
184
185 #[inline]
188 fn target_from_segment(
189 ptr: *const Self,
190 arena: &dyn ReaderArena,
191 segment_id: u32,
192 ) -> Result<*const u8> {
193 let this_addr: *const u8 = ptr as *const _;
194 unsafe { arena.check_offset(segment_id, this_addr, (*ptr).offset_in_words()) }
195 }
196
197 #[inline]
200 fn mut_target(ptr: *mut Self) -> *mut u8 {
201 let this_addr: *mut u8 = ptr as *mut _;
202 unsafe {
203 this_addr.wrapping_offset(
204 isize::try_from(BYTES_PER_WORD).unwrap() * (*ptr).offset_in_words() as isize,
205 )
206 }
207 }
208
209 #[inline]
210 pub(crate) fn set_kind_and_target(&mut self, kind: WirePointerKind, target: *mut u8) {
211 let this_addr: isize = self as *const _ as isize;
212 let target_addr: isize = target as *const _ as isize;
213 self.offset_and_kind.set(
214 ((i32::try_from((target_addr - this_addr) / isize::try_from(BYTES_PER_WORD).unwrap())
215 .unwrap()
216 - 1)
217 << 2) as u32
218 | (kind as u32),
219 )
220 }
221
222 #[inline]
223 pub(crate) fn set_kind_with_zero_offset(&mut self, kind: WirePointerKind) {
224 self.offset_and_kind.set(kind as u32)
225 }
226
227 #[inline]
228 pub(crate) fn set_kind_and_target_for_empty_struct(&mut self) {
229 self.offset_and_kind.set(0xfffffffc);
239 }
240
241 #[inline]
242 pub(crate) fn inline_composite_list_element_count(&self) -> ElementCount32 {
243 self.offset_and_kind.get() >> 2
244 }
245
246 #[inline]
247 pub(crate) fn set_kind_and_inline_composite_list_element_count(
248 &mut self,
249 kind: WirePointerKind,
250 element_count: ElementCount32,
251 ) {
252 self.offset_and_kind
253 .set((element_count << 2) | (kind as u32))
254 }
255
256 #[inline]
257 pub(crate) fn far_position_in_segment(&self) -> WordCount32 {
258 self.offset_and_kind.get() >> 3
259 }
260
261 #[inline]
262 pub(crate) fn is_double_far(&self) -> bool {
263 ((self.offset_and_kind.get() >> 2) & 1) != 0
264 }
265
266 #[inline]
267 pub(crate) fn set_far(&mut self, is_double_far: bool, pos: WordCount32) {
268 self.offset_and_kind
269 .set((pos << 3) | (u32::from(is_double_far) << 2) | WirePointerKind::Far as u32);
270 }
271
272 #[inline]
273 pub(crate) fn set_cap(&mut self, index: u32) {
274 self.offset_and_kind.set(WirePointerKind::Other as u32);
275 self.upper32bits.set(index);
276 }
277
278 #[inline]
279 pub(crate) fn struct_data_size(&self) -> WordCount16 {
280 (self.upper32bits.get() & 0xFFFF) as WordCount16
281 }
282
283 #[inline]
284 pub(crate) fn struct_ptr_count(&self) -> WordCount16 {
285 (self.upper32bits.get() >> 16) as WordCount16
286 }
287
288 #[inline]
289 pub(crate) fn struct_word_size(&self) -> WordCount32 {
290 u32::from(self.struct_data_size())
291 + u32::from(self.struct_ptr_count()) * u32::try_from(WORDS_PER_POINTER).unwrap()
292 }
293
294 #[inline]
295 pub(crate) fn set_struct_size(&mut self, size: StructSize) {
296 self.upper32bits
297 .set(u32::from(size.data) | (u32::from(size.pointers) << 16))
298 }
299
300 #[inline]
301 pub(crate) fn set_struct_size_from_pieces(&mut self, ds: WordCount16, rc: WirePointerCount16) {
302 self.set_struct_size(StructSize {
303 data: ds,
304 pointers: rc,
305 })
306 }
307
308 #[inline]
309 pub(crate) fn list_element_size(&self) -> ElementSize {
310 ElementSize::from((self.upper32bits.get() & 7) as u8)
311 }
312
313 #[inline]
314 pub(crate) fn list_element_count(&self) -> ElementCount32 {
315 self.upper32bits.get() >> 3
316 }
317
318 #[inline]
319 pub(crate) fn list_inline_composite_word_count(&self) -> WordCount32 {
320 self.list_element_count()
321 }
322
323 #[inline]
324 pub(crate) fn set_list_size_and_count(&mut self, es: ElementSize, ec: ElementCount32) {
325 assert!(ec < (1 << 29), "Lists are limited to 2**29 elements");
326 self.upper32bits.set((ec << 3) | (es as u32));
327 }
328
329 #[inline]
330 pub(crate) fn set_list_inline_composite(&mut self, wc: WordCount32) {
331 assert!(
332 wc < (1 << 29),
333 "Inline composite lists are limited to 2**29 words"
334 );
335 self.upper32bits.set((wc << 3) | (InlineComposite as u32));
336 }
337
338 #[inline]
339 pub(crate) fn far_segment_id(&self) -> SegmentId {
340 self.upper32bits.get() as SegmentId
341 }
342
343 #[inline]
344 pub(crate) fn set_far_segment_id(&mut self, si: SegmentId) {
345 self.upper32bits.set(si)
346 }
347
348 #[inline]
349 pub(crate) fn cap_index(&self) -> u32 {
350 self.upper32bits.get()
351 }
352
353 #[inline]
354 pub(crate) fn is_null(&self) -> bool {
355 self.offset_and_kind.get() == 0 && self.upper32bits.get() == 0
356 }
357}
358
359mod wire_helpers {
360 use core::{ptr, slice};
361
362 use crate::data;
363 use crate::private::arena::*;
364 #[cfg(feature = "alloc")]
365 use crate::private::capability::ClientHook;
366 use crate::private::layout::ElementSize::*;
367 use crate::private::layout::{data_bits_per_element, pointers_per_element};
368 use crate::private::layout::{CapTableBuilder, CapTableReader};
369 use crate::private::layout::{
370 ElementSize, ListBuilder, ListReader, PointerReader, StructBuilder, StructReader,
371 StructSize, WirePointer, WirePointerKind,
372 };
373 use crate::private::units::*;
374 use crate::text;
375 use crate::{Error, ErrorKind, MessageSize, Result};
376
377 pub(crate) struct SegmentAnd<T> {
378 #[allow(dead_code)]
379 segment_id: u32,
380 pub value: T,
381 }
382
383 #[inline]
384 pub(crate) fn round_bytes_up_to_words(bytes: ByteCount32) -> WordCount32 {
385 (bytes + 7) / u32::try_from(BYTES_PER_WORD).unwrap()
387 }
388
389 #[inline]
394 pub(crate) fn round_bits_up_to_words(bits: BitCount64) -> WordCount32 {
395 WordCount32::try_from((bits + 63) / (BITS_PER_WORD as u64)).unwrap()
397 }
398
399 #[inline]
400 pub(crate) fn round_bits_up_to_bytes(bits: BitCount64) -> ByteCount32 {
401 ByteCount32::try_from((bits + 7) / (BITS_PER_BYTE as u64)).unwrap()
402 }
403
404 #[inline]
405 pub(crate) fn bounds_check(
406 arena: &dyn ReaderArena,
407 segment_id: u32,
408 start: *const u8,
409 size_in_words: usize,
410 _kind: WirePointerKind,
411 ) -> Result<()> {
412 arena.contains_interval(segment_id, start, size_in_words)
413 }
414
415 #[inline]
416 pub(crate) fn amplified_read(arena: &dyn ReaderArena, virtual_amount: u64) -> Result<()> {
417 arena.amplified_read(virtual_amount)
418 }
419
420 #[inline]
421 pub(crate) unsafe fn copy_nonoverlapping_check_zero<T>(
422 src: *const T,
423 dst: *mut T,
424 count: usize,
425 ) {
426 if count > 0 {
427 ptr::copy_nonoverlapping(src, dst, count);
428 }
429 }
430
431 #[inline]
432 pub(crate) unsafe fn allocate(
433 arena: &mut dyn BuilderArena,
434 reff: *mut WirePointer,
435 segment_id: u32,
436 amount: WordCount32,
437 kind: WirePointerKind,
438 ) -> (*mut u8, *mut WirePointer, u32) {
439 let is_null = (*reff).is_null();
440 if !is_null {
441 zero_object(arena, segment_id, reff)
442 }
443
444 if amount == 0 && kind == WirePointerKind::Struct {
445 (*reff).set_kind_and_target_for_empty_struct();
446 return (reff as *mut _, reff, segment_id);
447 }
448
449 match arena.allocate(segment_id, amount) {
450 None => {
451 let amount_plus_ref = amount + u32::try_from(POINTER_SIZE_IN_WORDS).unwrap();
456 let (segment_id, word_idx) = arena.allocate_anywhere(amount_plus_ref);
457 let (seg_start, _seg_len) = arena.get_segment_mut(segment_id);
458 let ptr = seg_start.add(word_idx as usize * BYTES_PER_WORD);
459
460 (*reff).set_far(false, word_idx);
463 (*reff).set_far_segment_id(segment_id);
464
465 let reff = ptr as *mut WirePointer;
468
469 let ptr1 = ptr.add(BYTES_PER_WORD);
470 (*reff).set_kind_and_target(kind, ptr1);
471 (ptr1, reff, segment_id)
472 }
473 Some(idx) => {
474 let (seg_start, _seg_len) = arena.get_segment_mut(segment_id);
475 let ptr = seg_start.add(idx as usize * BYTES_PER_WORD);
476 (*reff).set_kind_and_target(kind, ptr);
477 (ptr, reff, segment_id)
478 }
479 }
480 }
481
482 #[inline]
483 pub(crate) unsafe fn follow_builder_fars(
484 arena: &mut dyn BuilderArena,
485 reff: *mut WirePointer,
486 ref_target: *mut u8,
487 segment_id: u32,
488 ) -> Result<(*mut u8, *mut WirePointer, u32)> {
489 if (*reff).kind() == WirePointerKind::Far {
499 let segment_id = (*reff).far_segment_id();
500 let (seg_start, _seg_len) = arena.get_segment_mut(segment_id);
501 let pad: *mut WirePointer =
502 (seg_start as *mut WirePointer).add((*reff).far_position_in_segment() as usize);
503 if !(*reff).is_double_far() {
504 Ok((WirePointer::mut_target(pad), pad, segment_id))
505 } else {
506 let reff = pad.add(1);
509
510 let segment_id = (*pad).far_segment_id();
511 let (segment_start, _segment_len) = arena.get_segment_mut(segment_id);
512 let ptr =
513 segment_start.add((*pad).far_position_in_segment() as usize * BYTES_PER_WORD);
514 Ok((ptr, reff, segment_id))
515 }
516 } else {
517 Ok((ref_target, reff, segment_id))
518 }
519 }
520
521 #[inline]
526 pub(crate) unsafe fn follow_fars(
527 arena: &dyn ReaderArena,
528 reff: *const WirePointer,
529 segment_id: u32,
530 ) -> Result<(*const u8, *const WirePointer, u32)> {
531 if (*reff).kind() == WirePointerKind::Far {
532 let far_segment_id = (*reff).far_segment_id();
533
534 let (seg_start, _seg_len) = arena.get_segment(far_segment_id)?;
535 let ptr =
539 seg_start.wrapping_add((*reff).far_position_in_segment() as usize * BYTES_PER_WORD);
540
541 let pad_words: usize = if (*reff).is_double_far() { 2 } else { 1 };
542 bounds_check(arena, far_segment_id, ptr, pad_words, WirePointerKind::Far)?;
543
544 let pad: *const WirePointer = ptr as *const _;
545
546 if !(*reff).is_double_far() {
547 Ok((
548 WirePointer::target_from_segment(pad, arena, far_segment_id)?,
549 pad,
550 far_segment_id,
551 ))
552 } else {
553 let tag = pad.add(1);
557 let double_far_segment_id = (*pad).far_segment_id();
558 let (segment_start, _segment_len) = arena.get_segment(double_far_segment_id)?;
559 let ptr = segment_start
563 .wrapping_add((*pad).far_position_in_segment() as usize * BYTES_PER_WORD);
564 Ok((ptr, tag, double_far_segment_id))
565 }
566 } else {
567 Ok((
568 WirePointer::target_from_segment(reff, arena, segment_id)?,
569 reff,
570 segment_id,
571 ))
572 }
573 }
574
575 pub(crate) unsafe fn zero_object(
576 arena: &mut dyn BuilderArena,
577 segment_id: u32,
578 reff: *mut WirePointer,
579 ) {
580 match (*reff).kind() {
585 WirePointerKind::Struct | WirePointerKind::List | WirePointerKind::Other => {
586 zero_object_helper(arena, segment_id, reff, WirePointer::mut_target(reff))
587 }
588 WirePointerKind::Far => {
589 let segment_id = (*reff).far_segment_id();
590 let (seg_start, _seg_len) = arena.get_segment_mut(segment_id);
591 let pad: *mut WirePointer =
592 (seg_start as *mut WirePointer).add((*reff).far_position_in_segment() as usize);
593
594 if (*reff).is_double_far() {
595 let segment_id = (*pad).far_segment_id();
596
597 let (seg_start, _seg_len) = arena.get_segment_mut(segment_id);
598 let ptr =
599 seg_start.add((*pad).far_position_in_segment() as usize * BYTES_PER_WORD);
600 zero_object_helper(arena, segment_id, pad.add(1), ptr);
601
602 ptr::write_bytes(pad, 0u8, 2);
603 } else {
604 zero_object(arena, segment_id, pad);
605 ptr::write_bytes(pad, 0u8, 1);
606 }
607 }
608 }
609 }
610
611 pub(crate) unsafe fn zero_object_helper(
612 arena: &mut dyn BuilderArena,
613 segment_id: u32,
614 tag: *mut WirePointer,
615 ptr: *mut u8,
616 ) {
617 match (*tag).kind() {
618 WirePointerKind::Other => {
619 panic!("Don't know how to handle OTHER")
620 }
621 WirePointerKind::Struct => {
622 let pointer_section: *mut WirePointer =
623 ptr.add((*tag).struct_data_size() as usize * BYTES_PER_WORD) as *mut _;
624
625 let count = (*tag).struct_ptr_count();
626 for i in 0..count {
627 zero_object(arena, segment_id, pointer_section.add(i as usize));
628 }
629 ptr::write_bytes(
630 ptr,
631 0u8,
632 (*tag).struct_word_size() as usize * BYTES_PER_WORD,
633 );
634 }
635 WirePointerKind::List => match (*tag).list_element_size() {
636 Void => {}
637 Bit | Byte | TwoBytes | FourBytes | EightBytes => ptr::write_bytes(
638 ptr,
639 0u8,
640 BYTES_PER_WORD
641 * round_bits_up_to_words(
642 u64::from((*tag).list_element_count())
643 * u64::from(data_bits_per_element((*tag).list_element_size())),
644 ) as usize,
645 ),
646 Pointer => {
647 let count = (*tag).list_element_count() as usize;
648 for i in 0..count {
649 zero_object(arena, segment_id, ptr.add(i * BYTES_PER_WORD) as *mut _);
650 }
651 ptr::write_bytes(ptr, 0u8, count * BYTES_PER_WORD);
652 }
653 InlineComposite => {
654 let element_tag: *mut WirePointer = ptr as *mut _;
655
656 assert!(
657 (*element_tag).kind() == WirePointerKind::Struct,
658 "Don't know how to handle non-STRUCT inline composite"
659 );
660
661 let data_size = (*element_tag).struct_data_size();
662 let pointer_count = (*element_tag).struct_ptr_count();
663 let mut pos = ptr.add(BYTES_PER_WORD);
664 let count = (*element_tag).inline_composite_list_element_count();
665 if pointer_count > 0 {
666 for _ in 0..count {
667 pos = pos.add(data_size as usize * BYTES_PER_WORD);
668 for _ in 0..pointer_count {
669 zero_object(arena, segment_id, pos as *mut WirePointer);
670 pos = pos.add(BYTES_PER_WORD);
671 }
672 }
673 }
674 ptr::write_bytes(
675 ptr,
676 0u8,
677 BYTES_PER_WORD * ((*element_tag).struct_word_size() * count + 1) as usize,
678 );
679 }
680 },
681 WirePointerKind::Far => {
682 panic!("Unexpected FAR pointer")
683 }
684 }
685 }
686
687 #[inline]
688 pub(crate) unsafe fn zero_pointer_and_fars(
689 arena: &mut dyn BuilderArena,
690 _segment_id: u32,
691 reff: *mut WirePointer,
692 ) -> Result<()> {
693 if (*reff).kind() == WirePointerKind::Far {
697 let far_segment_id = (*reff).far_segment_id();
698 let (seg_start, _seg_len) = arena.get_segment_mut(far_segment_id);
699 let pad = seg_start.add((*reff).far_position_in_segment() as usize * BYTES_PER_WORD);
700 let num_elements = if (*reff).is_double_far() { 2 } else { 1 };
701 ptr::write_bytes(pad, 0, num_elements * BYTES_PER_WORD);
702 }
703 ptr::write_bytes(reff, 0, 1);
704 Ok(())
705 }
706
707 pub(crate) unsafe fn total_size(
708 arena: &dyn ReaderArena,
709 segment_id: u32,
710 reff: *const WirePointer,
711 mut nesting_limit: i32,
712 ) -> Result<MessageSize> {
713 let mut result = MessageSize {
714 word_count: 0,
715 cap_count: 0,
716 };
717
718 if (*reff).is_null() {
719 return Ok(result);
720 };
721
722 if nesting_limit <= 0 {
723 return Err(Error::from_kind(ErrorKind::MessageIsTooDeeplyNested));
724 }
725
726 nesting_limit -= 1;
727
728 let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?;
729
730 match (*reff).kind() {
731 WirePointerKind::Struct => {
732 bounds_check(
733 arena,
734 segment_id,
735 ptr,
736 (*reff).struct_word_size() as usize,
737 WirePointerKind::Struct,
738 )?;
739 result.word_count += u64::from((*reff).struct_word_size());
740
741 let pointer_section: *const WirePointer =
742 ptr.add((*reff).struct_data_size() as usize * BYTES_PER_WORD) as *const _;
743 let count: usize = (*reff).struct_ptr_count() as usize;
744 for i in 0..count {
745 result += total_size(arena, segment_id, pointer_section.add(i), nesting_limit)?;
746 }
747 }
748 WirePointerKind::List => {
749 match (*reff).list_element_size() {
750 Void => {}
751 Bit | Byte | TwoBytes | FourBytes | EightBytes => {
752 let total_words = round_bits_up_to_words(
753 u64::from((*reff).list_element_count())
754 * u64::from(data_bits_per_element((*reff).list_element_size())),
755 );
756 bounds_check(
757 arena,
758 segment_id,
759 ptr,
760 total_words as usize,
761 WirePointerKind::List,
762 )?;
763 result.word_count += u64::from(total_words);
764 }
765 Pointer => {
766 let count = (*reff).list_element_count();
767 bounds_check(
768 arena,
769 segment_id,
770 ptr,
771 count as usize * WORDS_PER_POINTER,
772 WirePointerKind::List,
773 )?;
774
775 result.word_count += u64::from(count) * WORDS_PER_POINTER as u64;
776
777 for i in 0..count as usize {
778 result += total_size(
779 arena,
780 segment_id,
781 (ptr as *const WirePointer).add(i),
782 nesting_limit,
783 )?;
784 }
785 }
786 InlineComposite => {
787 let word_count = (*reff).list_inline_composite_word_count();
788 bounds_check(
789 arena,
790 segment_id,
791 ptr,
792 word_count as usize + POINTER_SIZE_IN_WORDS,
793 WirePointerKind::List,
794 )?;
795
796 let element_tag: *const WirePointer = ptr as *const _;
797 let count = (*element_tag).inline_composite_list_element_count();
798
799 if (*element_tag).kind() != WirePointerKind::Struct {
800 return Err(Error::from_kind(
801 ErrorKind::CantHandleNonStructInlineComposite,
802 ));
803 }
804
805 let actual_size =
806 u64::from((*element_tag).struct_word_size()) * u64::from(count);
807 if actual_size > u64::from(word_count) {
808 return Err(Error::from_kind(
809 ErrorKind::InlineCompositeListsElementsOverrunItsWordCount,
810 ));
811 }
812
813 result.word_count += actual_size + POINTER_SIZE_IN_WORDS as u64;
816
817 let data_size = (*element_tag).struct_data_size();
818 let pointer_count = (*element_tag).struct_ptr_count();
819
820 if pointer_count > 0 {
821 let mut pos = ptr.add(BYTES_PER_WORD);
822 for _ in 0..count {
823 pos = pos.add(data_size as usize * BYTES_PER_WORD);
824
825 for _ in 0..pointer_count {
826 result += total_size(
827 arena,
828 segment_id,
829 pos as *const WirePointer,
830 nesting_limit,
831 )?;
832 pos = pos.add(BYTES_PER_WORD);
833 }
834 }
835 }
836 }
837 }
838 }
839 WirePointerKind::Far => {
840 return Err(Error::from_kind(ErrorKind::MalformedDoubleFarPointer));
841 }
842 WirePointerKind::Other => {
843 if (*reff).is_capability() {
844 result.cap_count += 1;
845 } else {
846 return Err(Error::from_kind(ErrorKind::UnknownPointerType));
847 }
848 }
849 }
850
851 Ok(result)
852 }
853
854 unsafe fn copy_struct(
856 arena: &mut dyn BuilderArena,
857 segment_id: u32,
858 cap_table: CapTableBuilder,
859 dst: *mut u8,
860 src: *const u8,
861 data_size: usize,
862 pointer_count: usize,
863 ) {
864 copy_nonoverlapping_check_zero(src, dst, data_size * BYTES_PER_WORD);
865
866 let src_refs: *const WirePointer = (src as *const WirePointer).add(data_size);
867 let dst_refs: *mut WirePointer = (dst as *mut WirePointer).add(data_size);
868
869 for ii in 0..pointer_count {
870 copy_message(
871 arena,
872 segment_id,
873 cap_table,
874 dst_refs.add(ii),
875 src_refs.add(ii),
876 );
877 }
878 }
879
880 pub(crate) unsafe fn copy_message(
883 arena: &mut dyn BuilderArena,
884 segment_id: u32,
885 cap_table: CapTableBuilder,
886 dst: *mut WirePointer,
887 src: *const WirePointer,
888 ) -> (*mut u8, *mut WirePointer, u32) {
889 match (*src).kind() {
890 WirePointerKind::Struct => {
891 if (*src).is_null() {
892 ptr::write_bytes(dst, 0, 1);
893 (ptr::null_mut(), dst, segment_id)
894 } else {
895 let src_ptr = WirePointer::target(src);
896 let (dst_ptr, dst, segment_id) = allocate(
897 arena,
898 dst,
899 segment_id,
900 (*src).struct_word_size(),
901 WirePointerKind::Struct,
902 );
903 copy_struct(
904 arena,
905 segment_id,
906 cap_table,
907 dst_ptr,
908 src_ptr,
909 (*src).struct_data_size() as usize,
910 (*src).struct_ptr_count() as usize,
911 );
912 (*dst).set_struct_size_from_pieces(
913 (*src).struct_data_size(),
914 (*src).struct_ptr_count(),
915 );
916 (dst_ptr, dst, segment_id)
917 }
918 }
919 WirePointerKind::List => match (*src).list_element_size() {
920 ElementSize::Void
921 | ElementSize::Bit
922 | ElementSize::Byte
923 | ElementSize::TwoBytes
924 | ElementSize::FourBytes
925 | ElementSize::EightBytes => {
926 let word_count = round_bits_up_to_words(
927 u64::from((*src).list_element_count())
928 * u64::from(data_bits_per_element((*src).list_element_size())),
929 );
930 let src_ptr = WirePointer::target(src);
931 let (dst_ptr, dst, segment_id) =
932 allocate(arena, dst, segment_id, word_count, WirePointerKind::List);
933 copy_nonoverlapping_check_zero(
934 src_ptr,
935 dst_ptr,
936 word_count as usize * BYTES_PER_WORD,
937 );
938 (*dst).set_list_size_and_count(
939 (*src).list_element_size(),
940 (*src).list_element_count(),
941 );
942 (dst_ptr, dst, segment_id)
943 }
944
945 ElementSize::Pointer => {
946 let src_refs: *const WirePointer = WirePointer::target(src) as _;
947 let (dst_refs, dst, segment_id) = allocate(
948 arena,
949 dst,
950 segment_id,
951 (*src).list_element_count(),
952 WirePointerKind::List,
953 );
954 for ii in 0..((*src).list_element_count() as usize) {
955 copy_message(
956 arena,
957 segment_id,
958 cap_table,
959 dst_refs.add(ii * BYTES_PER_WORD) as *mut WirePointer,
960 src_refs.add(ii),
961 );
962 }
963 (*dst)
964 .set_list_size_and_count(ElementSize::Pointer, (*src).list_element_count());
965 (dst_refs, dst, segment_id)
966 }
967 ElementSize::InlineComposite => {
968 let src_ptr = WirePointer::target(src);
969 let (dst_ptr, dst, segment_id) = allocate(
970 arena,
971 dst,
972 segment_id,
973 (*src).list_inline_composite_word_count() + 1,
974 WirePointerKind::List,
975 );
976
977 (*dst).set_list_inline_composite((*src).list_inline_composite_word_count());
978
979 let src_tag: *const WirePointer = src_ptr as _;
980 ptr::copy_nonoverlapping(src_tag, dst_ptr as *mut WirePointer, 1);
981
982 let mut src_element = src_ptr.add(BYTES_PER_WORD);
983 let mut dst_element = dst_ptr.add(BYTES_PER_WORD);
984
985 if (*src_tag).kind() != WirePointerKind::Struct {
986 panic!("unsupported INLINE_COMPOSITE list");
987 }
988 for _ in 0..(*src_tag).inline_composite_list_element_count() {
989 copy_struct(
990 arena,
991 segment_id,
992 cap_table,
993 dst_element,
994 src_element,
995 (*src_tag).struct_data_size() as usize,
996 (*src_tag).struct_ptr_count() as usize,
997 );
998 src_element = src_element
999 .add(BYTES_PER_WORD * (*src_tag).struct_word_size() as usize);
1000 dst_element = dst_element
1001 .add(BYTES_PER_WORD * (*src_tag).struct_word_size() as usize);
1002 }
1003 (dst_ptr, dst, segment_id)
1004 }
1005 },
1006 WirePointerKind::Other => {
1007 panic!("Unchecked message contained an OTHER pointer.")
1008 }
1009 WirePointerKind::Far => {
1010 panic!("Unchecked message contained a far pointer.")
1011 }
1012 }
1013 }
1014
1015 pub(crate) unsafe fn transfer_pointer(
1016 arena: &mut dyn BuilderArena,
1017 dst_segment_id: u32,
1018 dst: *mut WirePointer,
1019 src_segment_id: u32,
1020 src: *mut WirePointer,
1021 ) {
1022 assert!((*dst).is_null());
1033 if (*src).is_null() {
1036 ptr::write_bytes(dst, 0, 1);
1037 } else if (*src).is_positional() {
1038 transfer_pointer_split(
1039 arena,
1040 dst_segment_id,
1041 dst,
1042 src_segment_id,
1043 src,
1044 WirePointer::mut_target(src),
1045 );
1046 } else {
1047 ptr::copy_nonoverlapping(src, dst, 1);
1048 }
1049 }
1050
1051 pub(crate) unsafe fn transfer_pointer_split(
1052 arena: &mut dyn BuilderArena,
1053 dst_segment_id: u32,
1054 dst: *mut WirePointer,
1055 src_segment_id: u32,
1056 src_tag: *mut WirePointer,
1057 src_ptr: *mut u8,
1058 ) {
1059 if dst_segment_id == src_segment_id {
1063 if (*src_tag).kind() == WirePointerKind::Struct && (*src_tag).struct_word_size() == 0 {
1066 (*dst).set_kind_and_target_for_empty_struct();
1067 } else {
1068 (*dst).set_kind_and_target((*src_tag).kind(), src_ptr);
1069 }
1070 ptr::copy_nonoverlapping(&(*src_tag).upper32bits, &mut (*dst).upper32bits, 1);
1072 } else {
1073 match arena.allocate(src_segment_id, 1) {
1077 None => {
1078 let (far_segment_id, word_idx) = arena.allocate_anywhere(2);
1080 let (seg_start, _seg_len) = arena.get_segment_mut(far_segment_id);
1081 let landing_pad: *mut WirePointer =
1082 (seg_start as *mut WirePointer).add(word_idx as usize);
1083
1084 let (src_seg_start, _seg_len) = arena.get_segment_mut(src_segment_id);
1085
1086 (*landing_pad).set_far(
1087 false,
1088 u32::try_from((src_ptr as usize - src_seg_start as usize) / BYTES_PER_WORD)
1089 .unwrap(),
1090 );
1091 (*landing_pad).set_far_segment_id(src_segment_id);
1092
1093 let landing_pad1 = landing_pad.add(1);
1094 (*landing_pad1).set_kind_with_zero_offset((*src_tag).kind());
1095
1096 ptr::copy_nonoverlapping(
1097 &(*src_tag).upper32bits,
1098 &mut (*landing_pad1).upper32bits,
1099 1,
1100 );
1101
1102 (*dst).set_far(true, word_idx);
1103 (*dst).set_far_segment_id(far_segment_id);
1104 }
1105 Some(landing_pad_word) => {
1106 let (seg_start, seg_len) = arena.get_segment_mut(src_segment_id);
1108 assert!(landing_pad_word < seg_len);
1109 let landing_pad: *mut WirePointer =
1110 (seg_start as *mut WirePointer).add(landing_pad_word as usize);
1111 (*landing_pad).set_kind_and_target((*src_tag).kind(), src_ptr);
1112 ptr::copy_nonoverlapping(
1113 &(*src_tag).upper32bits,
1114 &mut (*landing_pad).upper32bits,
1115 1,
1116 );
1117
1118 (*dst).set_far(false, landing_pad_word);
1119 (*dst).set_far_segment_id(src_segment_id);
1120 }
1121 }
1122 }
1123 }
1124
1125 #[inline]
1126 pub(crate) unsafe fn init_struct_pointer(
1127 arena: &mut dyn BuilderArena,
1128 reff: *mut WirePointer,
1129 segment_id: u32,
1130 cap_table: CapTableBuilder,
1131 size: StructSize,
1132 ) -> StructBuilder<'_> {
1133 let (ptr, reff, segment_id) = allocate(
1134 arena,
1135 reff,
1136 segment_id,
1137 size.total(),
1138 WirePointerKind::Struct,
1139 );
1140 (*reff).set_struct_size(size);
1141
1142 StructBuilder {
1143 arena,
1144 segment_id,
1145 cap_table,
1146 data: ptr as *mut _,
1147 pointers: ptr.add(size.data as usize * BYTES_PER_WORD) as *mut _,
1148 data_size: u32::from(size.data) * BitCount32::try_from(BITS_PER_WORD).unwrap(),
1149 pointer_count: size.pointers,
1150 }
1151 }
1152
1153 #[inline]
1154 pub(crate) unsafe fn get_writable_struct_pointer<'a>(
1155 arena: &'a mut dyn BuilderArena,
1156 mut reff: *mut WirePointer,
1157 mut segment_id: u32,
1158 cap_table: CapTableBuilder,
1159 size: StructSize,
1160 default: Option<&'a [crate::Word]>,
1161 ) -> Result<StructBuilder<'a>> {
1162 let mut ref_target = WirePointer::mut_target(reff);
1163
1164 if (*reff).is_null() {
1165 match default {
1166 None => {
1167 return Ok(init_struct_pointer(
1168 arena, reff, segment_id, cap_table, size,
1169 ))
1170 }
1171 Some(d) if (*(d.as_ptr() as *const WirePointer)).is_null() => {
1172 return Ok(init_struct_pointer(
1173 arena, reff, segment_id, cap_table, size,
1174 ))
1175 }
1176 Some(d) => {
1177 let (new_ref_target, new_reff, new_segment_id) = copy_message(
1178 arena,
1179 segment_id,
1180 cap_table,
1181 reff,
1182 d.as_ptr() as *const WirePointer,
1183 );
1184 reff = new_reff;
1185 segment_id = new_segment_id;
1186 ref_target = new_ref_target;
1187 }
1188 }
1189 }
1190
1191 let (old_ptr, old_ref, old_segment_id) =
1192 follow_builder_fars(arena, reff, ref_target, segment_id)?;
1193 if (*old_ref).kind() != WirePointerKind::Struct {
1194 return Err(Error::from_kind(
1195 ErrorKind::MessageContainsNonStructPointerWhereStructPointerWasExpected,
1196 ));
1197 }
1198
1199 let old_data_size = (*old_ref).struct_data_size();
1200 let old_pointer_count = (*old_ref).struct_ptr_count();
1201 let old_pointer_section: *mut WirePointer =
1202 old_ptr.add(old_data_size as usize * BYTES_PER_WORD) as *mut _;
1203
1204 if old_data_size < size.data || old_pointer_count < size.pointers {
1205 let new_data_size = ::core::cmp::max(old_data_size, size.data);
1212 let new_pointer_count = ::core::cmp::max(old_pointer_count, size.pointers);
1213 let total_size = u32::from(new_data_size)
1214 + u32::from(new_pointer_count) * u32::try_from(WORDS_PER_POINTER).unwrap();
1215
1216 zero_pointer_and_fars(arena, segment_id, reff)?;
1218
1219 let (ptr, reff, segment_id) =
1220 allocate(arena, reff, segment_id, total_size, WirePointerKind::Struct);
1221 (*reff).set_struct_size_from_pieces(new_data_size, new_pointer_count);
1222
1223 copy_nonoverlapping_check_zero(old_ptr, ptr, old_data_size as usize * BYTES_PER_WORD);
1226
1227 let new_pointer_section: *mut WirePointer =
1229 ptr.add(new_data_size as usize * BYTES_PER_WORD) as *mut _;
1230 for i in 0..old_pointer_count as usize {
1231 transfer_pointer(
1232 arena,
1233 segment_id,
1234 new_pointer_section.add(i),
1235 old_segment_id,
1236 old_pointer_section.add(i),
1237 );
1238 }
1239
1240 ptr::write_bytes(
1241 old_ptr,
1242 0,
1243 (old_data_size as usize + old_pointer_count as usize) * BYTES_PER_WORD,
1244 );
1245
1246 Ok(StructBuilder {
1247 arena,
1248 segment_id,
1249 cap_table,
1250 data: ptr as *mut _,
1251 pointers: new_pointer_section,
1252 data_size: u32::from(new_data_size) * u32::try_from(BITS_PER_WORD).unwrap(),
1253 pointer_count: new_pointer_count,
1254 })
1255 } else {
1256 Ok(StructBuilder {
1257 arena,
1258 segment_id: old_segment_id,
1259 cap_table,
1260 data: old_ptr,
1261 pointers: old_pointer_section,
1262 data_size: u32::from(old_data_size) * u32::try_from(BITS_PER_WORD).unwrap(),
1263 pointer_count: old_pointer_count,
1264 })
1265 }
1266 }
1267
1268 #[inline]
1269 pub(crate) unsafe fn init_list_pointer(
1270 arena: &mut dyn BuilderArena,
1271 reff: *mut WirePointer,
1272 segment_id: u32,
1273 cap_table: CapTableBuilder,
1274 element_count: ElementCount32,
1275 element_size: ElementSize,
1276 ) -> ListBuilder<'_> {
1277 assert!(
1278 element_size != InlineComposite,
1279 "Should have called initStructListPointer() instead"
1280 );
1281
1282 let data_size = data_bits_per_element(element_size);
1283 let pointer_count = pointers_per_element(element_size);
1284 let step = data_size + pointer_count * u32::try_from(BITS_PER_POINTER).unwrap();
1285 let word_count = round_bits_up_to_words(u64::from(element_count) * u64::from(step));
1286 let (ptr, reff, segment_id) =
1287 allocate(arena, reff, segment_id, word_count, WirePointerKind::List);
1288
1289 (*reff).set_list_size_and_count(element_size, element_count);
1290
1291 ListBuilder {
1292 arena,
1293 segment_id,
1294 cap_table,
1295 ptr,
1296 step,
1297 element_count,
1298 element_size,
1299 struct_data_size: data_size,
1300 struct_pointer_count: u16::try_from(pointer_count).unwrap(),
1301 }
1302 }
1303
1304 #[inline]
1305 pub(crate) unsafe fn init_struct_list_pointer(
1306 arena: &mut dyn BuilderArena,
1307 reff: *mut WirePointer,
1308 segment_id: u32,
1309 cap_table: CapTableBuilder,
1310 element_count: ElementCount32,
1311 element_size: StructSize,
1312 ) -> ListBuilder<'_> {
1313 let words_per_element = element_size.total();
1314
1315 let word_count_u64 = u64::from(element_count) * u64::from(words_per_element);
1317 assert!(
1318 word_count_u64 < (1 << 29),
1319 "Inline composite lists are limited to 2**29 words"
1320 );
1321 let word_count: WordCount32 = WordCount32::try_from(word_count_u64).unwrap();
1322 let (ptr, reff, segment_id) = allocate(
1323 arena,
1324 reff,
1325 segment_id,
1326 u32::try_from(POINTER_SIZE_IN_WORDS).unwrap() + word_count,
1327 WirePointerKind::List,
1328 );
1329 let ptr = ptr as *mut WirePointer;
1330
1331 (*reff).set_list_inline_composite(word_count);
1333 (*ptr).set_kind_and_inline_composite_list_element_count(
1334 WirePointerKind::Struct,
1335 element_count,
1336 );
1337 (*ptr).set_struct_size(element_size);
1338
1339 let ptr1 = ptr.add(POINTER_SIZE_IN_WORDS);
1340
1341 ListBuilder {
1342 arena,
1343 segment_id,
1344 cap_table,
1345 ptr: ptr1 as *mut _,
1346 step: words_per_element * u32::try_from(BITS_PER_WORD).unwrap(),
1347 element_count,
1348 element_size: ElementSize::InlineComposite,
1349 struct_data_size: u32::from(element_size.data)
1350 * (u32::try_from(BITS_PER_WORD).unwrap()),
1351 struct_pointer_count: element_size.pointers,
1352 }
1353 }
1354
1355 #[inline]
1356 pub(crate) unsafe fn get_writable_list_pointer(
1357 arena: &mut dyn BuilderArena,
1358 mut orig_ref: *mut WirePointer,
1359 mut orig_segment_id: u32,
1360 cap_table: CapTableBuilder,
1361 element_size: ElementSize,
1362 default_value: *const u8,
1363 ) -> Result<ListBuilder<'_>> {
1364 assert!(
1365 element_size != InlineComposite,
1366 "Use get_writable_struct_list_pointer() for struct lists"
1367 );
1368
1369 let mut orig_ref_target = WirePointer::mut_target(orig_ref);
1370
1371 if (*orig_ref).is_null() {
1372 if default_value.is_null() || (*(default_value as *const WirePointer)).is_null() {
1373 return Ok(ListBuilder::new_default(arena));
1374 }
1375 let (new_orig_ref_target, new_orig_ref, new_orig_segment_id) = copy_message(
1376 arena,
1377 orig_segment_id,
1378 cap_table,
1379 orig_ref,
1380 default_value as *const WirePointer,
1381 );
1382 orig_ref_target = new_orig_ref_target;
1383 orig_ref = new_orig_ref;
1384 orig_segment_id = new_orig_segment_id;
1385 }
1386
1387 let (mut ptr, reff, segment_id) =
1393 follow_builder_fars(arena, orig_ref, orig_ref_target, orig_segment_id)?;
1394
1395 if (*reff).kind() != WirePointerKind::List {
1396 return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList));
1397 }
1398
1399 let old_size = (*reff).list_element_size();
1400
1401 if old_size == InlineComposite {
1402 let tag: *const WirePointer = ptr as *const _;
1410
1411 if (*tag).kind() != WirePointerKind::Struct {
1412 return Err(Error::from_kind(
1413 ErrorKind::InlineCompositeListWithNonStructElementsNotSupported,
1414 ));
1415 }
1416
1417 ptr = ptr.add(BYTES_PER_WORD);
1418
1419 let data_size = (*tag).struct_data_size();
1420 let pointer_count = (*tag).struct_ptr_count();
1421
1422 match element_size {
1423 Void => {} Bit => {
1425 return Err(Error::from_kind(
1426 ErrorKind::FoundStructListWhereBitListWasExpected,
1427 ));
1428 }
1429 Byte | TwoBytes | FourBytes | EightBytes => {
1430 if data_size < 1 {
1431 return Err(Error::from_kind(
1432 ErrorKind::ExistingListValueIsIncompatibleWithExpectedType,
1433 ));
1434 }
1435 }
1436 Pointer => {
1437 if pointer_count < 1 {
1438 return Err(Error::from_kind(
1439 ErrorKind::ExistingListValueIsIncompatibleWithExpectedType,
1440 ));
1441 }
1442 ptr = ptr.add(data_size as usize * BYTES_PER_WORD);
1444 }
1445 InlineComposite => {
1446 unreachable!()
1447 }
1448 }
1449 Ok(ListBuilder {
1452 arena,
1453 segment_id,
1454 cap_table,
1455 ptr: ptr as *mut _,
1456 element_count: (*tag).inline_composite_list_element_count(),
1457 element_size: ElementSize::InlineComposite,
1458 step: (*tag).struct_word_size() * u32::try_from(BITS_PER_WORD).unwrap(),
1459 struct_data_size: u32::from(data_size) * u32::try_from(BITS_PER_WORD).unwrap(),
1460 struct_pointer_count: pointer_count,
1461 })
1462 } else {
1463 let data_size = data_bits_per_element(old_size);
1464 let pointer_count = pointers_per_element(old_size);
1465
1466 if data_size < data_bits_per_element(element_size)
1467 || pointer_count < pointers_per_element(element_size)
1468 {
1469 return Err(Error::from_kind(
1470 ErrorKind::ExistingListValueIsIncompatibleWithExpectedType,
1471 ));
1472 }
1473
1474 let step = data_size + pointer_count * u32::try_from(BITS_PER_POINTER).unwrap();
1475
1476 Ok(ListBuilder {
1477 arena,
1478 segment_id,
1479 cap_table,
1480 ptr: ptr as *mut _,
1481 step,
1482 element_count: (*reff).list_element_count(),
1483 element_size: old_size,
1484 struct_data_size: data_size,
1485 struct_pointer_count: u16::try_from(pointer_count).unwrap(),
1486 })
1487 }
1488 }
1489
1490 #[inline]
1491 pub(crate) unsafe fn get_writable_struct_list_pointer(
1492 arena: &mut dyn BuilderArena,
1493 mut orig_ref: *mut WirePointer,
1494 mut orig_segment_id: u32,
1495 cap_table: CapTableBuilder,
1496 element_size: StructSize,
1497 default_value: *const u8,
1498 ) -> Result<ListBuilder<'_>> {
1499 let mut orig_ref_target = WirePointer::mut_target(orig_ref);
1500
1501 if (*orig_ref).is_null() {
1502 if default_value.is_null() || (*(default_value as *const WirePointer)).is_null() {
1503 return Ok(ListBuilder::new_default(arena));
1504 }
1505 let (new_orig_ref_target, new_orig_ref, new_orig_segment_id) = copy_message(
1506 arena,
1507 orig_segment_id,
1508 cap_table,
1509 orig_ref,
1510 default_value as *const WirePointer,
1511 );
1512 orig_ref_target = new_orig_ref_target;
1513 orig_ref = new_orig_ref;
1514 orig_segment_id = new_orig_segment_id;
1515 }
1516
1517 let (mut old_ptr, old_ref, old_segment_id) =
1520 follow_builder_fars(arena, orig_ref, orig_ref_target, orig_segment_id)?;
1521
1522 if (*old_ref).kind() != WirePointerKind::List {
1523 return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList));
1524 }
1525
1526 let old_size = (*old_ref).list_element_size();
1527
1528 if old_size == InlineComposite {
1529 let old_tag: *const WirePointer = old_ptr as *const _;
1532 old_ptr = old_ptr.add(BYTES_PER_WORD);
1533 if (*old_tag).kind() != WirePointerKind::Struct {
1534 return Err(Error::from_kind(
1535 ErrorKind::InlineCompositeListWithNonStructElementsNotSupported,
1536 ));
1537 }
1538
1539 let old_data_size = (*old_tag).struct_data_size();
1540 let old_pointer_count = (*old_tag).struct_ptr_count();
1541 let old_step = u32::from(old_data_size)
1542 + u32::from(old_pointer_count) * u32::try_from(WORDS_PER_POINTER).unwrap();
1543 let element_count = (*old_tag).inline_composite_list_element_count();
1544
1545 if old_data_size >= element_size.data && old_pointer_count >= element_size.pointers {
1546 return Ok(ListBuilder {
1548 arena,
1549 segment_id: old_segment_id,
1550 cap_table,
1551 ptr: old_ptr as *mut _,
1552 element_count,
1553 element_size: ElementSize::InlineComposite,
1554 step: old_step * u32::try_from(BITS_PER_WORD).unwrap(),
1555 struct_data_size: u32::from(old_data_size)
1556 * u32::try_from(BITS_PER_WORD).unwrap(),
1557 struct_pointer_count: old_pointer_count,
1558 });
1559 }
1560
1561 let new_data_size = ::core::cmp::max(old_data_size, element_size.data);
1565 let new_pointer_count = ::core::cmp::max(old_pointer_count, element_size.pointers);
1566 let new_step = u32::from(new_data_size)
1567 + u32::from(new_pointer_count) * u32::try_from(WORDS_PER_POINTER).unwrap();
1568
1569 let total_size_u64 = u64::from(new_step) * u64::from(element_count);
1570 if total_size_u64 >= (1 << 29) {
1571 return Err(Error::from_kind(ErrorKind::MessageTooLarge(
1572 usize::try_from(total_size_u64).unwrap_or(usize::MAX),
1573 )));
1574 }
1575 let total_size = u32::try_from(total_size_u64).unwrap();
1576
1577 zero_pointer_and_fars(arena, orig_segment_id, orig_ref)?;
1579
1580 let (mut new_ptr, new_ref, new_segment_id) = allocate(
1581 arena,
1582 orig_ref,
1583 orig_segment_id,
1584 total_size + u32::try_from(POINTER_SIZE_IN_WORDS).unwrap(),
1585 WirePointerKind::List,
1586 );
1587 (*new_ref).set_list_inline_composite(total_size);
1588
1589 let new_tag: *mut WirePointer = new_ptr as *mut _;
1590 (*new_tag).set_kind_and_inline_composite_list_element_count(
1591 WirePointerKind::Struct,
1592 element_count,
1593 );
1594 (*new_tag).set_struct_size_from_pieces(new_data_size, new_pointer_count);
1595 new_ptr = new_ptr.add(BYTES_PER_WORD);
1596
1597 let mut src = old_ptr as *mut WirePointer;
1598 let mut dst = new_ptr as *mut WirePointer;
1599 for _ in 0..element_count {
1600 copy_nonoverlapping_check_zero(src, dst, old_data_size as usize);
1602
1603 let new_pointer_section = dst.add(new_data_size as usize);
1605 let old_pointer_section = src.add(old_data_size as usize);
1606 for jj in 0..(old_pointer_count as usize) {
1607 transfer_pointer(
1608 arena,
1609 new_segment_id,
1610 new_pointer_section.add(jj),
1611 old_segment_id,
1612 old_pointer_section.add(jj),
1613 );
1614 }
1615
1616 dst = dst.add(new_step as usize);
1617 src = src.add(old_step as usize);
1618 }
1619
1620 ptr::write_bytes(
1622 old_ptr.sub(BYTES_PER_WORD),
1623 0,
1624 (usize::try_from(u64::from(old_step) * u64::from(element_count)).unwrap()
1625 + POINTER_SIZE_IN_WORDS)
1626 * BYTES_PER_WORD,
1627 );
1628
1629 Ok(ListBuilder {
1630 arena,
1631 segment_id: new_segment_id,
1632 cap_table,
1633 ptr: new_ptr,
1634 element_count,
1635 element_size: ElementSize::InlineComposite,
1636 step: new_step * u32::try_from(BITS_PER_WORD).unwrap(),
1637 struct_data_size: u32::from(new_data_size) * u32::try_from(BITS_PER_WORD).unwrap(),
1638 struct_pointer_count: new_pointer_count,
1639 })
1640 } else {
1641 let old_data_size = data_bits_per_element(old_size);
1644 let old_pointer_count = pointers_per_element(old_size);
1645 let old_step =
1646 old_data_size + old_pointer_count * u32::try_from(BITS_PER_POINTER).unwrap();
1647 let element_count = (*old_ref).list_element_count();
1648
1649 if old_size == ElementSize::Void {
1650 Ok(init_struct_list_pointer(
1652 arena,
1653 orig_ref,
1654 orig_segment_id,
1655 cap_table,
1656 element_count,
1657 element_size,
1658 ))
1659 } else {
1660 if old_size == ElementSize::Bit {
1663 return Err(Error::from_kind(
1664 ErrorKind::FoundBitListWhereStructListWasExpected,
1665 ));
1666 }
1667
1668 let mut new_data_size = element_size.data;
1669 let mut new_pointer_count = element_size.pointers;
1670
1671 if old_size == ElementSize::Pointer {
1672 new_pointer_count = ::core::cmp::max(new_pointer_count, 1);
1673 } else {
1674 new_data_size = ::core::cmp::max(new_data_size, 1);
1676 }
1677
1678 let new_step = u32::from(new_data_size)
1679 + u32::from(new_pointer_count) * u32::try_from(WORDS_PER_POINTER).unwrap();
1680
1681 let total_words_u64 = u64::from(new_step) * u64::from(element_count);
1682 if total_words_u64 >= (1 << 29) {
1683 return Err(Error::from_kind(ErrorKind::MessageTooLarge(
1684 usize::try_from(total_words_u64).unwrap_or(usize::MAX),
1685 )));
1686 }
1687 let total_words = u32::try_from(total_words_u64).unwrap();
1688
1689 zero_pointer_and_fars(arena, orig_segment_id, orig_ref)?;
1691
1692 let (mut new_ptr, new_ref, new_segment_id) = allocate(
1693 arena,
1694 orig_ref,
1695 orig_segment_id,
1696 total_words + u32::try_from(POINTER_SIZE_IN_WORDS).unwrap(),
1697 WirePointerKind::List,
1698 );
1699 (*new_ref).set_list_inline_composite(total_words);
1700
1701 let tag: *mut WirePointer = new_ptr as *mut _;
1702 (*tag).set_kind_and_inline_composite_list_element_count(
1703 WirePointerKind::Struct,
1704 element_count,
1705 );
1706 (*tag).set_struct_size_from_pieces(new_data_size, new_pointer_count);
1707 new_ptr = new_ptr.add(BYTES_PER_WORD);
1708
1709 if old_size == ElementSize::Pointer {
1710 let mut dst = new_ptr.add(new_data_size as usize * BYTES_PER_WORD);
1711 let mut src: *mut WirePointer = old_ptr as *mut _;
1712 for _ in 0..element_count {
1713 transfer_pointer(arena, new_segment_id, dst as *mut _, old_segment_id, src);
1714 dst = dst.add(new_step as usize * BYTES_PER_WORD);
1715 src = src.add(1);
1716 }
1717 } else {
1718 let mut dst = new_ptr;
1719 let mut src: *mut u8 = old_ptr;
1720 let old_byte_step = old_data_size / u32::try_from(BITS_PER_BYTE).unwrap();
1721 for _ in 0..element_count {
1722 copy_nonoverlapping_check_zero(src, dst, old_byte_step as usize);
1723 src = src.add(old_byte_step as usize);
1724 dst = dst.add(new_step as usize * BYTES_PER_WORD);
1725 }
1726 }
1727
1728 ptr::write_bytes(
1730 old_ptr,
1731 0,
1732 round_bits_up_to_bytes(u64::from(old_step) * u64::from(element_count)) as usize,
1733 );
1734
1735 Ok(ListBuilder {
1736 arena,
1737 segment_id: new_segment_id,
1738 cap_table,
1739 ptr: new_ptr,
1740 element_count,
1741 element_size: ElementSize::InlineComposite,
1742 step: new_step * u32::try_from(BITS_PER_WORD).unwrap(),
1743 struct_data_size: u32::from(new_data_size)
1744 * u32::try_from(BITS_PER_WORD).unwrap(),
1745 struct_pointer_count: new_pointer_count,
1746 })
1747 }
1748 }
1749 }
1750
1751 #[inline]
1752 pub(crate) unsafe fn init_text_pointer(
1753 arena: &mut dyn BuilderArena,
1754 reff: *mut WirePointer,
1755 segment_id: u32,
1756 size: ByteCount32,
1757 ) -> SegmentAnd<text::Builder<'_>> {
1758 assert!(size < (1 << 29), "text size too large");
1759
1760 let byte_size = size + 1;
1762
1763 let (ptr, reff, segment_id) = allocate(
1765 arena,
1766 reff,
1767 segment_id,
1768 round_bytes_up_to_words(byte_size),
1769 WirePointerKind::List,
1770 );
1771
1772 (*reff).set_list_size_and_count(Byte, byte_size);
1774
1775 SegmentAnd {
1776 segment_id,
1777 value: text::Builder::new(slice::from_raw_parts_mut(ptr, size as usize)),
1778 }
1779 }
1780
1781 #[inline]
1782 pub(crate) unsafe fn set_text_pointer<'a>(
1783 arena: &'a mut dyn BuilderArena,
1784 reff: *mut WirePointer,
1785 segment_id: u32,
1786 value: crate::text::Reader<'_>,
1787 ) -> SegmentAnd<text::Builder<'a>> {
1788 let value_bytes = value.as_bytes();
1789 let mut allocation = init_text_pointer(
1791 arena,
1792 reff,
1793 segment_id,
1794 u32::try_from(value_bytes.len()).expect("Text len does not fit in u32"),
1795 );
1796 allocation
1797 .value
1798 .reborrow()
1799 .as_bytes_mut()
1800 .copy_from_slice(value_bytes);
1801 allocation
1802 }
1803
1804 #[inline]
1805 pub(crate) unsafe fn get_writable_text_pointer<'a>(
1806 arena: &'a mut dyn BuilderArena,
1807 mut reff: *mut WirePointer,
1808 mut segment_id: u32,
1809 default: Option<&'a [crate::Word]>,
1810 ) -> Result<text::Builder<'a>> {
1811 let ref_target = if (*reff).is_null() {
1812 match default {
1813 None => return Ok(text::Builder::new(&mut [])),
1814 Some(d) => {
1815 let (new_ref_target, new_reff, new_segment_id) = copy_message(
1816 arena,
1817 segment_id,
1818 Default::default(),
1819 reff,
1820 d.as_ptr() as *const _,
1821 );
1822 reff = new_reff;
1823 segment_id = new_segment_id;
1824 new_ref_target
1825 }
1826 }
1827 } else {
1828 WirePointer::mut_target(reff)
1829 };
1830
1831 let (ptr, reff, _segment_id) = follow_builder_fars(arena, reff, ref_target, segment_id)?;
1832
1833 if (*reff).kind() != WirePointerKind::List {
1834 return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList));
1835 }
1836 if (*reff).list_element_size() != Byte {
1837 return Err(Error::from_kind(
1838 ErrorKind::ExistingListPointerIsNotByteSized,
1839 ));
1840 }
1841
1842 let count = (*reff).list_element_count();
1843 if count == 0 || *ptr.add((count - 1) as usize) != 0 {
1844 return Err(Error::from_kind(ErrorKind::TextBlobMissingNULTerminator));
1845 }
1846
1847 Ok(text::Builder::with_pos(
1849 slice::from_raw_parts_mut(ptr, (count - 1) as usize),
1850 (count - 1) as usize,
1851 ))
1852 }
1853
1854 #[inline]
1855 pub(crate) unsafe fn init_data_pointer(
1856 arena: &mut dyn BuilderArena,
1857 reff: *mut WirePointer,
1858 segment_id: u32,
1859 size: ByteCount32,
1860 ) -> SegmentAnd<data::Builder<'_>> {
1861 let (ptr, reff, segment_id) = allocate(
1863 arena,
1864 reff,
1865 segment_id,
1866 round_bytes_up_to_words(size),
1867 WirePointerKind::List,
1868 );
1869
1870 (*reff).set_list_size_and_count(Byte, size);
1872
1873 SegmentAnd {
1874 segment_id,
1875 value: data::builder_from_raw_parts(ptr, size),
1876 }
1877 }
1878
1879 #[inline]
1880 pub(crate) unsafe fn set_data_pointer<'a>(
1881 arena: &'a mut dyn BuilderArena,
1882 reff: *mut WirePointer,
1883 segment_id: u32,
1884 value: &[u8],
1885 ) -> SegmentAnd<data::Builder<'a>> {
1886 let allocation = init_data_pointer(
1887 arena,
1888 reff,
1889 segment_id,
1890 value.len().try_into().expect("data too large"),
1891 );
1892 allocation.value.copy_from_slice(value);
1893 allocation
1894 }
1895
1896 #[inline]
1897 pub(crate) unsafe fn get_writable_data_pointer<'a>(
1898 arena: &'a mut dyn BuilderArena,
1899 mut reff: *mut WirePointer,
1900 mut segment_id: u32,
1901 default: Option<&'a [crate::Word]>,
1902 ) -> Result<data::Builder<'a>> {
1903 let ref_target = if (*reff).is_null() {
1904 match default {
1905 None => return Ok(&mut []),
1906 Some(d) => {
1907 let (new_ref_target, new_reff, new_segment_id) = copy_message(
1908 arena,
1909 segment_id,
1910 Default::default(),
1911 reff,
1912 d.as_ptr() as *const _,
1913 );
1914 reff = new_reff;
1915 segment_id = new_segment_id;
1916 new_ref_target
1917 }
1918 }
1919 } else {
1920 WirePointer::mut_target(reff)
1921 };
1922
1923 let (ptr, reff, _segment_id) = follow_builder_fars(arena, reff, ref_target, segment_id)?;
1924
1925 if (*reff).kind() != WirePointerKind::List {
1926 return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList));
1927 }
1928 if (*reff).list_element_size() != Byte {
1929 return Err(Error::from_kind(
1930 ErrorKind::ExistingListPointerIsNotByteSized,
1931 ));
1932 }
1933
1934 Ok(data::builder_from_raw_parts(
1935 ptr,
1936 (*reff).list_element_count(),
1937 ))
1938 }
1939
1940 pub(crate) unsafe fn set_struct_pointer(
1941 arena: &mut dyn BuilderArena,
1942 segment_id: u32,
1943 cap_table: CapTableBuilder,
1944 reff: *mut WirePointer,
1945 value: StructReader,
1946 canonicalize: bool,
1947 ) -> Result<SegmentAnd<*mut u8>> {
1948 let mut data_size: ByteCount32 = round_bits_up_to_bytes(u64::from(value.data_size));
1949 let mut ptr_count = value.pointer_count;
1950
1951 if canonicalize {
1952 if !(value.data_size == 1
1954 || value.data_size % u32::try_from(BITS_PER_BYTE).unwrap() == 0)
1955 {
1956 return Err(Error::from_kind(
1957 ErrorKind::StructReaderHadBitwidthOtherThan1,
1958 ));
1959 }
1960
1961 if value.data_size == 1 {
1962 if !value.get_bool_field(0) {
1963 data_size = 0;
1964 }
1965 } else {
1966 'chop: while data_size != 0 {
1967 let end = data_size;
1968 let mut window = data_size % u32::try_from(BYTES_PER_WORD).unwrap();
1969 if window == 0 {
1970 window = u32::try_from(BYTES_PER_WORD).unwrap();
1971 }
1972 let start = end - window;
1973 let last_word = &value.get_data_section_as_blob()[start as usize..end as usize];
1974 if last_word == [0; 8] {
1975 data_size -= window;
1976 } else {
1977 break 'chop;
1978 }
1979 }
1980 }
1981
1982 while ptr_count != 0 && value.get_pointer_field(ptr_count as usize - 1).is_null() {
1983 ptr_count -= 1;
1984 }
1985 }
1986
1987 let data_words = round_bytes_up_to_words(data_size);
1988 let total_size: WordCount32 =
1989 data_words + u32::from(ptr_count) * u32::try_from(WORDS_PER_POINTER).unwrap();
1990
1991 let (ptr, reff, segment_id) =
1992 allocate(arena, reff, segment_id, total_size, WirePointerKind::Struct);
1993 (*reff).set_struct_size_from_pieces(u16::try_from(data_words).unwrap(), ptr_count);
1994
1995 if value.data_size == 1 {
1996 if data_size != 0 {
1998 *ptr = u8::from(value.get_bool_field(0))
1999 }
2000 } else {
2001 copy_nonoverlapping_check_zero::<u8>(value.data, ptr, data_size as usize);
2002 }
2003
2004 let pointer_section: *mut WirePointer =
2005 ptr.add(data_words as usize * BYTES_PER_WORD) as *mut _;
2006 for i in 0..ptr_count as usize {
2007 deep_copy_pointee(
2008 arena,
2009 segment_id,
2010 cap_table,
2011 pointer_section.add(i),
2012 value.get_pointer_field(i),
2013 canonicalize,
2014 )?;
2015 }
2016
2017 Ok(SegmentAnd {
2018 segment_id,
2019 value: ptr,
2020 })
2021 }
2022
2023 #[cfg(feature = "alloc")]
2024 pub(crate) unsafe fn set_capability_pointer(
2025 _arena: &mut dyn BuilderArena,
2026 _segment_id: u32,
2027 mut cap_table: CapTableBuilder,
2028 reff: *mut WirePointer,
2029 cap: alloc::boxed::Box<dyn ClientHook>,
2030 ) {
2031 (*reff).set_cap(u32::try_from(cap_table.inject_cap(cap)).unwrap());
2033 }
2034
2035 pub(crate) unsafe fn set_list_pointer(
2036 arena: &mut dyn BuilderArena,
2037 segment_id: u32,
2038 cap_table: CapTableBuilder,
2039 reff: *mut WirePointer,
2040 value: ListReader,
2041 canonicalize: bool,
2042 ) -> Result<SegmentAnd<*mut u8>> {
2043 let total_size =
2044 round_bits_up_to_words(u64::from(value.element_count) * u64::from(value.step));
2045
2046 if value.element_size != ElementSize::InlineComposite {
2047 let (ptr, reff, segment_id) =
2049 allocate(arena, reff, segment_id, total_size, WirePointerKind::List);
2050
2051 if value.struct_pointer_count == 1 {
2052 (*reff).set_list_size_and_count(Pointer, value.element_count);
2054 for i in 0..value.element_count {
2055 deep_copy_pointee(
2056 arena,
2057 segment_id,
2058 cap_table,
2059 (ptr as *mut WirePointer).add(i as usize),
2060 value.get_pointer_element(i),
2061 canonicalize,
2062 )?;
2063 }
2064 } else {
2065 let element_size = match value.step {
2067 0 => Void,
2068 1 => Bit,
2069 8 => Byte,
2070 16 => TwoBytes,
2071 32 => FourBytes,
2072 64 => EightBytes,
2073 _ => {
2074 panic!("invalid list step size: {}", value.step)
2075 }
2076 };
2077
2078 (*reff).set_list_size_and_count(element_size, value.element_count);
2079
2080 let whole_byte_size =
2085 u64::from(value.element_count) * u64::from(value.step) / BITS_PER_BYTE as u64;
2086 copy_nonoverlapping_check_zero(
2087 value.ptr,
2088 ptr,
2089 usize::try_from(whole_byte_size).unwrap(),
2090 );
2091
2092 let leftover_bits = u8::try_from(
2093 u64::from(value.element_count) * u64::from(value.step)
2094 % u64::try_from(BITS_PER_BYTE).unwrap(),
2095 )
2096 .unwrap();
2097 if leftover_bits > 0 {
2098 let mask: u8 = (1 << leftover_bits) - 1;
2099
2100 *ptr.add(usize::try_from(whole_byte_size).unwrap()) =
2101 mask & (*value.ptr.add(usize::try_from(whole_byte_size).unwrap()))
2102 }
2103 }
2104
2105 Ok(SegmentAnd {
2106 segment_id,
2107 value: ptr,
2108 })
2109 } else {
2110 let decl_data_size = value.struct_data_size / u32::try_from(BITS_PER_WORD).unwrap();
2113 let decl_pointer_count = value.struct_pointer_count;
2114
2115 let mut data_size = 0;
2116 let mut ptr_count = 0;
2117 let mut total_size = total_size;
2118
2119 if canonicalize {
2120 for ec in 0..value.element_count {
2121 let se = value.get_struct_element(ec);
2122 let mut local_data_size = decl_data_size;
2123 'data_chop: while local_data_size != 0 {
2124 let end = local_data_size * u32::try_from(BYTES_PER_WORD).unwrap();
2125 let window = u32::try_from(BYTES_PER_WORD).unwrap();
2126 let start = end - window;
2127 let last_word =
2128 &se.get_data_section_as_blob()[start as usize..end as usize];
2129 if last_word != [0; 8] {
2130 break 'data_chop;
2131 } else {
2132 local_data_size -= 1;
2133 }
2134 }
2135 if local_data_size > data_size {
2136 data_size = local_data_size;
2137 }
2138 let mut local_ptr_count = decl_pointer_count;
2139 while local_ptr_count != 0
2140 && se.get_pointer_field(local_ptr_count as usize - 1).is_null()
2141 {
2142 local_ptr_count -= 1;
2143 }
2144 if local_ptr_count > ptr_count {
2145 ptr_count = local_ptr_count;
2146 }
2147 }
2148 total_size = (data_size + u32::from(ptr_count)) * value.element_count;
2149 } else {
2150 data_size = decl_data_size;
2151 ptr_count = decl_pointer_count;
2152 }
2153
2154 let (ptr, reff, segment_id) = allocate(
2155 arena,
2156 reff,
2157 segment_id,
2158 total_size + u32::try_from(POINTER_SIZE_IN_WORDS).unwrap(),
2159 WirePointerKind::List,
2160 );
2161 (*reff).set_list_inline_composite(total_size);
2162
2163 let tag: *mut WirePointer = ptr as *mut _;
2164 (*tag).set_kind_and_inline_composite_list_element_count(
2165 WirePointerKind::Struct,
2166 value.element_count,
2167 );
2168 (*tag).set_struct_size_from_pieces(u16::try_from(data_size).unwrap(), ptr_count);
2169 let mut dst = ptr.add(BYTES_PER_WORD);
2170
2171 let mut src: *const u8 = value.ptr;
2172 for _ in 0..value.element_count {
2173 copy_nonoverlapping_check_zero(src, dst, data_size as usize * BYTES_PER_WORD);
2174 dst = dst.add(data_size as usize * BYTES_PER_WORD);
2175 src = src.add(decl_data_size as usize * BYTES_PER_WORD);
2176
2177 for _ in 0..ptr_count {
2178 let src_pr = PointerReader {
2179 arena: value.arena,
2180 segment_id: value.segment_id,
2181 cap_table: value.cap_table,
2182 pointer: src as *const WirePointer,
2183 nesting_limit: value.nesting_limit,
2184 };
2185 deep_copy_pointee(
2186 arena,
2187 segment_id,
2188 cap_table,
2189 dst as *mut _,
2190 src_pr,
2191 canonicalize,
2192 )?;
2193 dst = dst.add(BYTES_PER_WORD);
2194 src = src.add(BYTES_PER_WORD);
2195 }
2196
2197 src = src.add(
2198 decl_pointer_count.checked_sub(ptr_count).unwrap() as usize * BYTES_PER_WORD,
2199 );
2200 }
2201 Ok(SegmentAnd {
2202 segment_id,
2203 value: ptr,
2204 })
2205 }
2206 }
2207
2208 pub(crate) unsafe fn deep_copy_pointee(
2209 dst_arena: &mut dyn BuilderArena,
2210 dst_segment_id: u32,
2211 dst_cap_table: CapTableBuilder,
2212 dst: *mut WirePointer,
2213 src: PointerReader,
2214 canonicalize: bool,
2215 ) -> Result<SegmentAnd<*mut u8>> {
2216 if (*src.pointer).is_null() {
2217 ptr::write_bytes(dst, 0, 1);
2218 return Ok(SegmentAnd {
2219 segment_id: dst_segment_id,
2220 value: ptr::null_mut(),
2221 });
2222 }
2223
2224 let (mut ptr, src_ptr, src_segment_id) =
2225 follow_fars(src.arena, src.pointer, src.segment_id)?;
2226
2227 match (*src_ptr).kind() {
2228 WirePointerKind::Struct => {
2229 if src.nesting_limit <= 0 {
2230 return Err(Error::from_kind(
2231 ErrorKind::MessageIsTooDeeplyNestedOrContainsCycles,
2232 ));
2233 }
2234
2235 bounds_check(
2236 src.arena,
2237 src_segment_id,
2238 ptr,
2239 (*src_ptr).struct_word_size() as usize,
2240 WirePointerKind::Struct,
2241 )?;
2242
2243 set_struct_pointer(
2244 dst_arena,
2245 dst_segment_id,
2246 dst_cap_table,
2247 dst,
2248 StructReader {
2249 arena: src.arena,
2250 segment_id: src_segment_id,
2251 cap_table: src.cap_table,
2252 data: ptr,
2253 pointers: ptr.add((*src_ptr).struct_data_size() as usize * BYTES_PER_WORD)
2254 as *const _,
2255 data_size: u32::from((*src_ptr).struct_data_size())
2256 * u32::try_from(BITS_PER_WORD).unwrap(),
2257 pointer_count: (*src_ptr).struct_ptr_count(),
2258 nesting_limit: src.nesting_limit - 1,
2259 },
2260 canonicalize,
2261 )
2262 }
2263 WirePointerKind::List => {
2264 let element_size = (*src_ptr).list_element_size();
2265 if src.nesting_limit <= 0 {
2266 return Err(Error::from_kind(
2267 ErrorKind::MessageIsTooDeeplyNestedOrContainsCycles,
2268 ));
2269 }
2270
2271 if element_size == InlineComposite {
2272 let word_count = (*src_ptr).list_inline_composite_word_count();
2273
2274 bounds_check(
2279 src.arena,
2280 src_segment_id,
2281 ptr,
2282 word_count as usize + 1,
2283 WirePointerKind::List,
2284 )?;
2285
2286 let tag: *const WirePointer = ptr as *const _;
2287 ptr = ptr.add(BYTES_PER_WORD);
2288
2289 if (*tag).kind() != WirePointerKind::Struct {
2290 return Err(Error::from_kind(
2291 ErrorKind::InlineCompositeListsOfNonStructTypeAreNotSupported,
2292 ));
2293 }
2294
2295 let element_count = (*tag).inline_composite_list_element_count();
2296 let words_per_element = (*tag).struct_word_size();
2297
2298 if u64::from(words_per_element) * u64::from(element_count)
2299 > u64::from(word_count)
2300 {
2301 return Err(Error::from_kind(
2302 ErrorKind::InlineCompositeListsElementsOverrunItsWordCount,
2303 ));
2304 }
2305
2306 if words_per_element == 0 {
2307 amplified_read(src.arena, u64::from(element_count))?;
2310 }
2311
2312 set_list_pointer(
2313 dst_arena,
2314 dst_segment_id,
2315 dst_cap_table,
2316 dst,
2317 ListReader {
2318 arena: src.arena,
2319 segment_id: src_segment_id,
2320 cap_table: src.cap_table,
2321 ptr: ptr as *const _,
2322 element_count,
2323 element_size,
2324 step: words_per_element * u32::try_from(BITS_PER_WORD).unwrap(),
2325 struct_data_size: u32::from((*tag).struct_data_size())
2326 * u32::try_from(BITS_PER_WORD).unwrap(),
2327 struct_pointer_count: (*tag).struct_ptr_count(),
2328 nesting_limit: src.nesting_limit - 1,
2329 },
2330 canonicalize,
2331 )
2332 } else {
2333 let data_size = data_bits_per_element(element_size);
2334 let pointer_count = pointers_per_element(element_size);
2335 let step = data_size + pointer_count * u32::try_from(BITS_PER_POINTER).unwrap();
2336 let element_count = (*src_ptr).list_element_count();
2337 let word_count =
2338 round_bits_up_to_words(u64::from(element_count) * u64::from(step));
2339
2340 bounds_check(
2341 src.arena,
2342 src_segment_id,
2343 ptr,
2344 word_count as usize,
2345 WirePointerKind::List,
2346 )?;
2347
2348 if element_size == Void {
2349 amplified_read(src.arena, u64::from(element_count))?;
2352 }
2353
2354 set_list_pointer(
2355 dst_arena,
2356 dst_segment_id,
2357 dst_cap_table,
2358 dst,
2359 ListReader {
2360 arena: src.arena,
2361 segment_id: src_segment_id,
2362 cap_table: src.cap_table,
2363 ptr: ptr as *const _,
2364 element_count,
2365 element_size,
2366 step,
2367 struct_data_size: data_size,
2368 struct_pointer_count: u16::try_from(pointer_count).unwrap(),
2369 nesting_limit: src.nesting_limit - 1,
2370 },
2371 canonicalize,
2372 )
2373 }
2374 }
2375 WirePointerKind::Far => Err(Error::from_kind(ErrorKind::MalformedDoubleFarPointer)),
2376 WirePointerKind::Other => {
2377 if !(*src_ptr).is_capability() {
2378 return Err(Error::from_kind(ErrorKind::UnknownPointerType));
2379 }
2380 if canonicalize {
2381 return Err(Error::from_kind(
2382 ErrorKind::CannotCreateACanonicalMessageWithACapability,
2383 ));
2384 }
2385 #[cfg(feature = "alloc")]
2386 match src.cap_table.extract_cap((*src_ptr).cap_index() as usize) {
2387 Some(cap) => {
2388 set_capability_pointer(dst_arena, dst_segment_id, dst_cap_table, dst, cap);
2389 Ok(SegmentAnd {
2390 segment_id: dst_segment_id,
2391 value: ptr::null_mut(),
2392 })
2393 }
2394 None => Err(Error::from_kind(
2395 ErrorKind::MessageContainsInvalidCapabilityPointer,
2396 )),
2397 }
2398 #[cfg(not(feature = "alloc"))]
2399 return Err(Error::from_kind(ErrorKind::UnknownPointerType));
2400 }
2401 }
2402 }
2403
2404 #[inline]
2405 pub(crate) unsafe fn read_struct_pointer<'a>(
2406 mut arena: &'a dyn ReaderArena,
2407 mut segment_id: u32,
2408 cap_table: CapTableReader,
2409 mut reff: *const WirePointer,
2410 default: Option<&'a [crate::Word]>,
2411 nesting_limit: i32,
2412 ) -> Result<StructReader<'a>> {
2413 if (*reff).is_null() {
2414 match default {
2415 None => return Ok(StructReader::new_default()),
2416 Some(d) if (*(d.as_ptr() as *const WirePointer)).is_null() => {
2417 return Ok(StructReader::new_default())
2418 }
2419 Some(d) => {
2420 reff = d.as_ptr() as *const _;
2421 arena = &super::NULL_ARENA;
2422 segment_id = 0;
2423 }
2424 }
2425 }
2426
2427 if nesting_limit <= 0 {
2428 return Err(Error::from_kind(
2429 ErrorKind::MessageIsTooDeeplyNestedOrContainsCycles,
2430 ));
2431 }
2432
2433 let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?;
2434
2435 let data_size_words = (*reff).struct_data_size();
2436
2437 if (*reff).kind() != WirePointerKind::Struct {
2438 return Err(Error::from_kind(
2439 ErrorKind::MessageContainsNonStructPointerWhereStructPointerWasExpected,
2440 ));
2441 }
2442
2443 bounds_check(
2444 arena,
2445 segment_id,
2446 ptr,
2447 (*reff).struct_word_size() as usize,
2448 WirePointerKind::Struct,
2449 )?;
2450
2451 Ok(StructReader {
2452 arena,
2453 segment_id,
2454 cap_table,
2455 data: ptr,
2456 pointers: ptr.add(data_size_words as usize * BYTES_PER_WORD) as *const _,
2457 data_size: u32::from(data_size_words) * u32::try_from(BITS_PER_WORD).unwrap(),
2458 pointer_count: (*reff).struct_ptr_count(),
2459 nesting_limit: nesting_limit - 1,
2460 })
2461 }
2462
2463 #[inline]
2464 #[cfg(feature = "alloc")]
2465 pub(crate) unsafe fn read_capability_pointer(
2466 _arena: &dyn ReaderArena,
2467 _segment_id: u32,
2468 cap_table: CapTableReader,
2469 reff: *const WirePointer,
2470 _nesting_limit: i32,
2471 ) -> Result<alloc::boxed::Box<dyn ClientHook>> {
2472 if (*reff).is_null() {
2473 Err(Error::from_kind(
2474 ErrorKind::MessageContainsNullCapabilityPointer,
2475 ))
2476 } else if !(*reff).is_capability() {
2477 Err(Error::from_kind(
2478 ErrorKind::MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected,
2479 ))
2480 } else {
2481 let n = (*reff).cap_index() as usize;
2482 match cap_table.extract_cap(n) {
2483 Some(client_hook) => Ok(client_hook),
2484 None => Err(Error::from_kind(
2485 ErrorKind::MessageContainsInvalidCapabilityPointer,
2486 )),
2487 }
2488 }
2489 }
2490
2491 #[inline]
2492 pub(crate) unsafe fn read_list_pointer(
2493 mut arena: &dyn ReaderArena,
2494 mut segment_id: u32,
2495 cap_table: CapTableReader,
2496 mut reff: *const WirePointer,
2497 default_value: *const u8,
2498 expected_element_size: Option<ElementSize>,
2499 nesting_limit: i32,
2500 ) -> Result<ListReader<'_>> {
2501 if (*reff).is_null() {
2502 if default_value.is_null() || (*(default_value as *const WirePointer)).is_null() {
2503 return Ok(ListReader::new_default());
2504 }
2505 reff = default_value as *const _;
2506 arena = &super::NULL_ARENA;
2507 segment_id = 0;
2508 }
2509
2510 if nesting_limit <= 0 {
2511 return Err(Error::from_kind(ErrorKind::NestingLimitExceeded));
2512 }
2513 let (mut ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?;
2514
2515 if (*reff).kind() != WirePointerKind::List {
2516 return Err(Error::from_kind(
2517 ErrorKind::MessageContainsNonListPointerWhereListPointerWasExpected,
2518 ));
2519 }
2520
2521 let element_size = (*reff).list_element_size();
2522 match element_size {
2523 InlineComposite => {
2524 let word_count = (*reff).list_inline_composite_word_count();
2525
2526 bounds_check(
2532 arena,
2533 segment_id,
2534 ptr,
2535 word_count as usize + 1,
2536 WirePointerKind::List,
2537 )?;
2538
2539 let tag: *const WirePointer = ptr as *const WirePointer;
2540
2541 ptr = ptr.add(BYTES_PER_WORD);
2542
2543 if (*tag).kind() != WirePointerKind::Struct {
2544 return Err(Error::from_kind(
2545 ErrorKind::InlineCompositeListsOfNonStructTypeAreNotSupported,
2546 ));
2547 }
2548
2549 let size = (*tag).inline_composite_list_element_count();
2550 let data_size = (*tag).struct_data_size();
2551 let ptr_count = (*tag).struct_ptr_count();
2552 let words_per_element = (*tag).struct_word_size();
2553
2554 if u64::from(size) * u64::from(words_per_element) > u64::from(word_count) {
2555 return Err(Error::from_kind(
2556 ErrorKind::InlineCompositeListsElementsOverrunItsWordCount,
2557 ));
2558 }
2559
2560 if words_per_element == 0 {
2561 amplified_read(arena, u64::from(size))?;
2564 }
2565
2566 match expected_element_size {
2573 None | Some(Void | InlineComposite) => (),
2574 Some(Bit) => {
2575 return Err(Error::from_kind(
2576 ErrorKind::FoundStructListWhereBitListWasExpected,
2577 ));
2578 }
2579 Some(Byte | TwoBytes | FourBytes | EightBytes) => {
2580 if data_size == 0 {
2581 return Err(Error::from_kind(
2582 ErrorKind::ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs,
2583 ));
2584 }
2585 }
2586 Some(Pointer) => {
2587 if ptr_count == 0 {
2588 return Err(Error::from_kind(
2589 ErrorKind::ExpectedAPointerListButGotAListOfDataOnlyStructs,
2590 ));
2591 }
2592 }
2593 }
2594
2595 Ok(ListReader {
2596 arena,
2597 segment_id,
2598 cap_table,
2599 ptr: ptr as *const _,
2600 element_count: size,
2601 element_size,
2602 step: words_per_element * u32::try_from(BITS_PER_WORD).unwrap(),
2603 struct_data_size: u32::from(data_size)
2604 * (u32::try_from(BITS_PER_WORD).unwrap()),
2605 struct_pointer_count: ptr_count,
2606 nesting_limit: nesting_limit - 1,
2607 })
2608 }
2609 _ => {
2610 let data_size = data_bits_per_element((*reff).list_element_size());
2614 let pointer_count = pointers_per_element((*reff).list_element_size());
2615 let element_count = (*reff).list_element_count();
2616 let step = data_size + pointer_count * u32::try_from(BITS_PER_POINTER).unwrap();
2617
2618 let word_count = round_bits_up_to_words(u64::from(element_count) * u64::from(step));
2619 bounds_check(
2620 arena,
2621 segment_id,
2622 ptr,
2623 word_count as usize,
2624 WirePointerKind::List,
2625 )?;
2626
2627 if element_size == Void {
2628 amplified_read(arena, u64::from(element_count))?;
2631 }
2632
2633 if let Some(expected_element_size) = expected_element_size {
2634 if element_size == ElementSize::Bit && expected_element_size != ElementSize::Bit
2635 {
2636 return Err(Error::from_kind(
2637 ErrorKind::FoundBitListWhereStructListWasExpected,
2638 ));
2639 }
2640
2641 let expected_data_bits_per_element =
2647 data_bits_per_element(expected_element_size);
2648 let expected_pointers_per_element = pointers_per_element(expected_element_size);
2649
2650 if expected_data_bits_per_element > data_size
2651 || expected_pointers_per_element > pointer_count
2652 {
2653 return Err(Error::from_kind(
2654 ErrorKind::MessageContainsListWithIncompatibleElementType,
2655 ));
2656 }
2657 }
2658
2659 Ok(ListReader {
2660 arena,
2661 segment_id,
2662 cap_table,
2663 ptr: ptr as *const _,
2664 element_count,
2665 element_size,
2666 step,
2667 struct_data_size: data_size,
2668 struct_pointer_count: u16::try_from(pointer_count).unwrap(),
2669 nesting_limit: nesting_limit - 1,
2670 })
2671 }
2672 }
2673 }
2674
2675 #[inline]
2676 pub(crate) unsafe fn read_text_pointer<'a>(
2677 mut arena: &'a dyn ReaderArena,
2678 mut segment_id: u32,
2679 mut reff: *const WirePointer,
2680 default: Option<&[crate::Word]>,
2681 ) -> Result<text::Reader<'a>> {
2682 if (*reff).is_null() {
2683 match default {
2684 None => return Ok("".into()),
2685 Some(d) => {
2686 reff = d.as_ptr() as *const WirePointer;
2687 arena = &super::NULL_ARENA;
2688 segment_id = 0;
2689 }
2690 }
2691 }
2692
2693 let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?;
2694 let size = (*reff).list_element_count();
2695
2696 if (*reff).kind() != WirePointerKind::List {
2697 return Err(Error::from_kind(
2698 ErrorKind::MessageContainsNonListPointerWhereTextWasExpected,
2699 ));
2700 }
2701
2702 if (*reff).list_element_size() != Byte {
2703 return Err(Error::from_kind(
2704 ErrorKind::MessageContainsListPointerOfNonBytesWhereTextWasExpected,
2705 ));
2706 }
2707
2708 bounds_check(
2709 arena,
2710 segment_id,
2711 ptr,
2712 round_bytes_up_to_words(size) as usize,
2713 WirePointerKind::List,
2714 )?;
2715
2716 if size == 0 {
2717 return Err(Error::from_kind(
2718 ErrorKind::MessageContainsTextThatIsNotNULTerminated,
2719 ));
2720 }
2721
2722 let str_ptr = ptr;
2723
2724 if (*str_ptr.add((size - 1) as usize)) != 0u8 {
2725 return Err(Error::from_kind(
2726 ErrorKind::MessageContainsTextThatIsNotNULTerminated,
2727 ));
2728 }
2729
2730 Ok(text::Reader(slice::from_raw_parts(
2731 str_ptr,
2732 size as usize - 1,
2733 )))
2734 }
2735
2736 #[inline]
2737 pub(crate) unsafe fn read_data_pointer<'a>(
2738 mut arena: &'a dyn ReaderArena,
2739 mut segment_id: u32,
2740 mut reff: *const WirePointer,
2741 default: Option<&'a [crate::Word]>,
2742 ) -> Result<data::Reader<'a>> {
2743 if (*reff).is_null() {
2744 match default {
2745 None => return Ok(&[]),
2746 Some(d) => {
2747 reff = d.as_ptr() as *const WirePointer;
2748 arena = &super::NULL_ARENA;
2749 segment_id = 0;
2750 }
2751 }
2752 }
2753
2754 let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?;
2755
2756 let size: u32 = (*reff).list_element_count();
2757
2758 if (*reff).kind() != WirePointerKind::List {
2759 return Err(Error::from_kind(
2760 ErrorKind::MessageContainsNonListPointerWhereDataWasExpected,
2761 ));
2762 }
2763
2764 if (*reff).list_element_size() != Byte {
2765 return Err(Error::from_kind(
2766 ErrorKind::MessageContainsListPointerOfNonBytesWhereDataWasExpected,
2767 ));
2768 }
2769
2770 bounds_check(
2771 arena,
2772 segment_id,
2773 ptr,
2774 round_bytes_up_to_words(size) as usize,
2775 WirePointerKind::List,
2776 )?;
2777
2778 Ok(data::reader_from_raw_parts(ptr as *const _, size))
2779 }
2780}
2781
2782static ZERO: u64 = 0;
2783fn zero_pointer() -> *const WirePointer {
2784 &ZERO as *const _ as *const _
2785}
2786
2787static NULL_ARENA: NullArena = NullArena;
2788
2789#[cfg(feature = "alloc")]
2790pub type CapTable = alloc::vec::Vec<Option<alloc::boxed::Box<dyn ClientHook>>>;
2791
2792#[cfg(not(feature = "alloc"))]
2793pub struct CapTable;
2794
2795#[derive(Copy, Clone, Default)]
2796pub enum CapTableReader {
2797 #[default]
2798 Dummy,
2799 Plain(core::ptr::NonNull<CapTable>),
2800}
2801
2802const _: () =
2803 assert!(core::mem::size_of::<CapTableReader>() == core::mem::size_of::<*const CapTable>());
2804
2805impl CapTableReader {
2806 pub fn from_ref(cap_table: &CapTable) -> Self {
2807 Self::Plain(core::ptr::NonNull::from(cap_table))
2808 }
2809
2810 #[cfg(feature = "alloc")]
2811 pub(crate) fn extract_cap(&self, index: usize) -> Option<alloc::boxed::Box<dyn ClientHook>> {
2812 match *self {
2813 Self::Dummy => None,
2814 Self::Plain(hooks) => {
2815 let hooks: &alloc::vec::Vec<Option<alloc::boxed::Box<dyn ClientHook>>> =
2816 unsafe { hooks.as_ref() };
2817 if index >= hooks.len() {
2818 None
2819 } else {
2820 hooks[index].as_ref().map(|hook| hook.add_ref())
2821 }
2822 }
2823 }
2824 }
2825}
2826
2827#[derive(Copy, Clone, Default)]
2828pub enum CapTableBuilder {
2829 #[default]
2830 Dummy,
2831 Plain(core::ptr::NonNull<CapTable>),
2832}
2833
2834const _: () =
2835 assert!(core::mem::size_of::<CapTableBuilder>() == core::mem::size_of::<*mut CapTable>());
2836
2837impl CapTableBuilder {
2838 pub fn into_reader(self) -> CapTableReader {
2839 match self {
2840 Self::Dummy => CapTableReader::Dummy,
2841 Self::Plain(hooks) => CapTableReader::Plain(hooks),
2842 }
2843 }
2844
2845 pub fn from_ref(cap_table: &mut CapTable) -> Self {
2846 Self::Plain(core::ptr::NonNull::from(cap_table))
2847 }
2848
2849 #[cfg(feature = "alloc")]
2850 pub(crate) fn inject_cap(&mut self, cap: alloc::boxed::Box<dyn ClientHook>) -> usize {
2851 match *self {
2852 Self::Dummy => {
2853 panic!(
2854 "Called inject_cap() on a null capability table. You need \
2855 to call imbue_mut() on this message before adding capabilities."
2856 );
2857 }
2858 Self::Plain(mut hooks) => {
2859 let hooks: &mut alloc::vec::Vec<Option<alloc::boxed::Box<dyn ClientHook>>> =
2860 unsafe { hooks.as_mut() };
2861 hooks.push(Some(cap));
2862 hooks.len() - 1
2863 }
2864 }
2865 }
2866
2867 #[cfg(feature = "alloc")]
2868 pub fn drop_cap(&mut self, index: usize) {
2869 match *self {
2870 Self::Dummy => {
2871 panic!(
2872 "Called drop_cap() on a null capability table. You need \
2873 to call imbue_mut() on this message before adding capabilities."
2874 );
2875 }
2876 Self::Plain(mut hooks) => {
2877 let hooks: &mut alloc::vec::Vec<Option<alloc::boxed::Box<dyn ClientHook>>> =
2878 unsafe { hooks.as_mut() };
2879 if index < hooks.len() {
2880 hooks[index] = None;
2881 }
2882 }
2883 }
2884 }
2885}
2886
2887#[derive(Clone, Copy)]
2888pub struct PointerReader<'a> {
2889 arena: &'a dyn ReaderArena,
2890 cap_table: CapTableReader,
2891 pointer: *const WirePointer,
2892 segment_id: u32,
2893 nesting_limit: i32,
2894}
2895
2896impl<'a> PointerReader<'a> {
2897 pub(crate) fn new_default<'b>() -> PointerReader<'b> {
2898 PointerReader {
2899 arena: &NULL_ARENA,
2900 segment_id: 0,
2901 cap_table: Default::default(),
2902 pointer: ptr::null(),
2903 nesting_limit: 0x7fffffff,
2904 }
2905 }
2906
2907 pub(crate) unsafe fn get_root(
2908 arena: &'a dyn ReaderArena,
2909 segment_id: u32,
2910 location: *const u8,
2911 nesting_limit: i32,
2912 ) -> Result<Self> {
2913 wire_helpers::bounds_check(
2914 arena,
2915 segment_id,
2916 location as *const _,
2917 POINTER_SIZE_IN_WORDS,
2918 WirePointerKind::Struct,
2919 )?;
2920
2921 Ok(PointerReader {
2922 arena,
2923 segment_id,
2924 cap_table: Default::default(),
2925 pointer: location as *const _,
2926 nesting_limit,
2927 })
2928 }
2929
2930 pub fn reborrow(&self) -> PointerReader<'_> {
2931 PointerReader {
2932 arena: self.arena,
2933 ..*self
2934 }
2935 }
2936
2937 #[cfg(test)]
2938 pub(crate) unsafe fn get_root_unchecked<'b>(location: *const u8) -> PointerReader<'b> {
2939 PointerReader {
2940 arena: &NULL_ARENA,
2941 segment_id: 0,
2942 cap_table: Default::default(),
2943 pointer: location as *const _,
2944 nesting_limit: 0x7fffffff,
2945 }
2946 }
2947
2948 pub fn get_root_from_arena(arena: &'a dyn ReaderArena) -> Result<Self> {
2949 let (segment_start, _seg_len) = arena.get_segment(0)?;
2950
2951 wire_helpers::bounds_check(
2952 arena,
2953 0,
2954 segment_start as *const _,
2955 POINTER_SIZE_IN_WORDS,
2956 WirePointerKind::Struct,
2957 )?;
2958
2959 Ok(PointerReader {
2960 arena,
2961 segment_id: 0,
2962 cap_table: Default::default(),
2963 pointer: segment_start as *const _,
2964 nesting_limit: arena.nesting_limit(),
2965 })
2966 }
2967
2968 pub fn imbue(&mut self, cap_table: CapTableReader) {
2969 self.cap_table = cap_table;
2970 }
2971
2972 #[inline]
2973 pub fn is_null(&self) -> bool {
2974 self.pointer.is_null() || unsafe { (*self.pointer).is_null() }
2975 }
2976
2977 pub fn total_size(&self) -> Result<MessageSize> {
2978 if self.pointer.is_null() {
2979 Ok(MessageSize {
2980 word_count: 0,
2981 cap_count: 0,
2982 })
2983 } else {
2984 unsafe {
2985 wire_helpers::total_size(
2986 self.arena,
2987 self.segment_id,
2988 self.pointer,
2989 self.nesting_limit,
2990 )
2991 }
2992 }
2993 }
2994
2995 pub fn get_struct(self, default: Option<&'a [crate::Word]>) -> Result<StructReader<'a>> {
2996 let reff: *const WirePointer = if self.pointer.is_null() {
2997 zero_pointer()
2998 } else {
2999 self.pointer
3000 };
3001 unsafe {
3002 wire_helpers::read_struct_pointer(
3003 self.arena,
3004 self.segment_id,
3005 self.cap_table,
3006 reff,
3007 default,
3008 self.nesting_limit,
3009 )
3010 }
3011 }
3012
3013 pub fn get_list(
3014 self,
3015 expected_element_size: ElementSize,
3016 default: Option<&'a [crate::Word]>,
3017 ) -> Result<ListReader<'a>> {
3018 let default_value: *const u8 = match default {
3019 None => core::ptr::null(),
3020 Some(d) => d.as_ptr() as *const u8,
3021 };
3022 let reff = if self.pointer.is_null() {
3023 zero_pointer()
3024 } else {
3025 self.pointer
3026 };
3027 unsafe {
3028 wire_helpers::read_list_pointer(
3029 self.arena,
3030 self.segment_id,
3031 self.cap_table,
3032 reff,
3033 default_value,
3034 Some(expected_element_size),
3035 self.nesting_limit,
3036 )
3037 }
3038 }
3039
3040 fn get_list_any_size(self, default_value: *const u8) -> Result<ListReader<'a>> {
3041 let reff = if self.pointer.is_null() {
3042 zero_pointer()
3043 } else {
3044 self.pointer
3045 };
3046 unsafe {
3047 wire_helpers::read_list_pointer(
3048 self.arena,
3049 self.segment_id,
3050 self.cap_table,
3051 reff,
3052 default_value,
3053 None,
3054 self.nesting_limit,
3055 )
3056 }
3057 }
3058
3059 pub fn get_text(self, default: Option<&[crate::Word]>) -> Result<text::Reader<'a>> {
3060 let reff = if self.pointer.is_null() {
3061 zero_pointer()
3062 } else {
3063 self.pointer
3064 };
3065 unsafe { wire_helpers::read_text_pointer(self.arena, self.segment_id, reff, default) }
3066 }
3067
3068 pub fn get_data(&self, default: Option<&'a [crate::Word]>) -> Result<data::Reader<'a>> {
3069 let reff = if self.pointer.is_null() {
3070 zero_pointer()
3071 } else {
3072 self.pointer
3073 };
3074 unsafe { wire_helpers::read_data_pointer(self.arena, self.segment_id, reff, default) }
3075 }
3076
3077 #[cfg(feature = "alloc")]
3078 pub fn get_capability(&self) -> Result<alloc::boxed::Box<dyn ClientHook>> {
3079 let reff: *const WirePointer = if self.pointer.is_null() {
3080 zero_pointer()
3081 } else {
3082 self.pointer
3083 };
3084 unsafe {
3085 wire_helpers::read_capability_pointer(
3086 self.arena,
3087 self.segment_id,
3088 self.cap_table,
3089 reff,
3090 self.nesting_limit,
3091 )
3092 }
3093 }
3094
3095 pub fn get_pointer_type(&self) -> Result<PointerType> {
3096 if self.is_null() {
3097 Ok(PointerType::Null)
3098 } else {
3099 let (_, reff, _) =
3100 unsafe { wire_helpers::follow_fars(self.arena, self.pointer, self.segment_id)? };
3101
3102 match unsafe { (*reff).kind() } {
3103 WirePointerKind::Far => Err(Error::from_kind(ErrorKind::UnexpectedFarPointer)),
3104 WirePointerKind::Struct => Ok(PointerType::Struct),
3105 WirePointerKind::List => Ok(PointerType::List),
3106 WirePointerKind::Other => {
3107 if unsafe { (*reff).is_capability() } {
3108 Ok(PointerType::Capability)
3109 } else {
3110 Err(Error::from_kind(ErrorKind::UnknownPointerType))
3111 }
3112 }
3113 }
3114 }
3115 }
3116
3117 pub fn is_canonical(&self, read_head: &Cell<*const u8>) -> Result<bool> {
3118 if self.pointer.is_null() || unsafe { !(*self.pointer).is_positional() } {
3119 return Ok(false);
3120 }
3121
3122 match self.get_pointer_type()? {
3123 PointerType::Null => Ok(true),
3124 PointerType::Struct => {
3125 let mut data_trunc = false;
3126 let mut ptr_trunc = false;
3127 let st = self.get_struct(None)?;
3128 if st.get_data_section_size() == 0 && st.get_pointer_section_size() == 0 {
3129 Ok(self.pointer as *const _ == st.get_location())
3130 } else {
3131 let result =
3132 st.is_canonical(read_head, read_head, &mut data_trunc, &mut ptr_trunc)?;
3133 Ok(result && data_trunc && ptr_trunc)
3134 }
3135 }
3136 PointerType::List => unsafe {
3137 self.get_list_any_size(ptr::null())?
3138 .is_canonical(read_head, self.pointer)
3139 },
3140 PointerType::Capability => Ok(false),
3141 }
3142 }
3143}
3144
3145pub struct PointerBuilder<'a> {
3146 arena: &'a mut dyn BuilderArena,
3147 segment_id: u32,
3148 cap_table: CapTableBuilder,
3149 pointer: *mut WirePointer,
3150}
3151
3152impl<'a> PointerBuilder<'a> {
3153 #[inline]
3154 pub fn get_root(arena: &'a mut dyn BuilderArena, segment_id: u32, location: *mut u8) -> Self {
3155 PointerBuilder {
3156 arena,
3157 cap_table: Default::default(),
3158 segment_id,
3159 pointer: location as *mut _,
3160 }
3161 }
3162
3163 #[inline]
3164 pub fn reborrow(&mut self) -> PointerBuilder<'_> {
3165 PointerBuilder {
3166 arena: self.arena,
3167 ..*self
3168 }
3169 }
3170
3171 pub fn imbue(&mut self, cap_table: CapTableBuilder) {
3172 self.cap_table = cap_table;
3173 }
3174
3175 #[inline]
3176 pub fn is_null(&self) -> bool {
3177 unsafe { (*self.pointer).is_null() }
3178 }
3179
3180 pub fn get_struct(
3181 self,
3182 size: StructSize,
3183 default: Option<&'a [crate::Word]>,
3184 ) -> Result<StructBuilder<'a>> {
3185 unsafe {
3186 wire_helpers::get_writable_struct_pointer(
3187 self.arena,
3188 self.pointer,
3189 self.segment_id,
3190 self.cap_table,
3191 size,
3192 default,
3193 )
3194 }
3195 }
3196
3197 pub fn get_list(
3198 self,
3199 element_size: ElementSize,
3200 default: Option<&'a [crate::Word]>,
3201 ) -> Result<ListBuilder<'a>> {
3202 let default_value: *const u8 = match default {
3203 None => core::ptr::null(),
3204 Some(d) => d.as_ptr() as *const u8,
3205 };
3206 unsafe {
3207 wire_helpers::get_writable_list_pointer(
3208 self.arena,
3209 self.pointer,
3210 self.segment_id,
3211 self.cap_table,
3212 element_size,
3213 default_value,
3214 )
3215 }
3216 }
3217
3218 pub fn get_struct_list(
3219 self,
3220 element_size: StructSize,
3221 default: Option<&'a [crate::Word]>,
3222 ) -> Result<ListBuilder<'a>> {
3223 let default_value: *const u8 = match default {
3224 None => core::ptr::null(),
3225 Some(d) => d.as_ptr() as *const u8,
3226 };
3227 unsafe {
3228 wire_helpers::get_writable_struct_list_pointer(
3229 self.arena,
3230 self.pointer,
3231 self.segment_id,
3232 self.cap_table,
3233 element_size,
3234 default_value,
3235 )
3236 }
3237 }
3238
3239 pub fn get_text(self, default: Option<&'a [crate::Word]>) -> Result<text::Builder<'a>> {
3240 unsafe {
3241 wire_helpers::get_writable_text_pointer(
3242 self.arena,
3243 self.pointer,
3244 self.segment_id,
3245 default,
3246 )
3247 }
3248 }
3249
3250 pub fn get_data(self, default: Option<&'a [crate::Word]>) -> Result<data::Builder<'a>> {
3251 unsafe {
3252 wire_helpers::get_writable_data_pointer(
3253 self.arena,
3254 self.pointer,
3255 self.segment_id,
3256 default,
3257 )
3258 }
3259 }
3260
3261 #[cfg(feature = "alloc")]
3262 pub fn get_capability(&self) -> Result<alloc::boxed::Box<dyn ClientHook>> {
3263 unsafe {
3264 wire_helpers::read_capability_pointer(
3265 self.arena.as_reader(),
3266 self.segment_id,
3267 self.cap_table.into_reader(),
3268 self.pointer,
3269 i32::MAX,
3270 )
3271 }
3272 }
3273
3274 pub fn init_struct(self, size: StructSize) -> StructBuilder<'a> {
3275 unsafe {
3276 wire_helpers::init_struct_pointer(
3277 self.arena,
3278 self.pointer,
3279 self.segment_id,
3280 self.cap_table,
3281 size,
3282 )
3283 }
3284 }
3285
3286 pub fn init_list(
3287 self,
3288 element_size: ElementSize,
3289 element_count: ElementCount32,
3290 ) -> ListBuilder<'a> {
3291 unsafe {
3292 wire_helpers::init_list_pointer(
3293 self.arena,
3294 self.pointer,
3295 self.segment_id,
3296 self.cap_table,
3297 element_count,
3298 element_size,
3299 )
3300 }
3301 }
3302
3303 pub fn init_struct_list(
3304 self,
3305 element_count: ElementCount32,
3306 element_size: StructSize,
3307 ) -> ListBuilder<'a> {
3308 unsafe {
3309 wire_helpers::init_struct_list_pointer(
3310 self.arena,
3311 self.pointer,
3312 self.segment_id,
3313 self.cap_table,
3314 element_count,
3315 element_size,
3316 )
3317 }
3318 }
3319
3320 pub fn init_text(self, size: ByteCount32) -> text::Builder<'a> {
3321 unsafe {
3322 wire_helpers::init_text_pointer(self.arena, self.pointer, self.segment_id, size).value
3323 }
3324 }
3325
3326 pub fn init_data(self, size: ByteCount32) -> data::Builder<'a> {
3327 unsafe {
3328 wire_helpers::init_data_pointer(self.arena, self.pointer, self.segment_id, size).value
3329 }
3330 }
3331
3332 pub fn set_struct(&mut self, value: &StructReader, canonicalize: bool) -> Result<()> {
3333 unsafe {
3334 wire_helpers::set_struct_pointer(
3335 self.arena,
3336 self.segment_id,
3337 self.cap_table,
3338 self.pointer,
3339 *value,
3340 canonicalize,
3341 )?;
3342 Ok(())
3343 }
3344 }
3345
3346 pub fn set_list(&mut self, value: &ListReader, canonicalize: bool) -> Result<()> {
3347 unsafe {
3348 wire_helpers::set_list_pointer(
3349 self.arena,
3350 self.segment_id,
3351 self.cap_table,
3352 self.pointer,
3353 *value,
3354 canonicalize,
3355 )?;
3356 Ok(())
3357 }
3358 }
3359
3360 pub fn set_text(&mut self, value: crate::text::Reader<'_>) {
3361 unsafe {
3362 wire_helpers::set_text_pointer(self.arena, self.pointer, self.segment_id, value);
3363 }
3364 }
3365
3366 pub fn set_data(&mut self, value: &[u8]) {
3367 unsafe {
3368 wire_helpers::set_data_pointer(self.arena, self.pointer, self.segment_id, value);
3369 }
3370 }
3371
3372 #[cfg(feature = "alloc")]
3373 pub fn set_capability(&mut self, cap: alloc::boxed::Box<dyn ClientHook>) {
3374 unsafe {
3375 wire_helpers::set_capability_pointer(
3376 self.arena,
3377 self.segment_id,
3378 self.cap_table,
3379 self.pointer,
3380 cap,
3381 );
3382 }
3383 }
3384
3385 pub(crate) fn copy_from(&mut self, other: PointerReader, canonicalize: bool) -> Result<()> {
3386 if other.pointer.is_null() {
3387 if !self.pointer.is_null() {
3388 unsafe {
3389 wire_helpers::zero_object(self.arena, self.segment_id, self.pointer);
3390 *self.pointer = mem::zeroed();
3391 }
3392 }
3393 } else {
3394 unsafe {
3395 wire_helpers::deep_copy_pointee(
3396 self.arena,
3397 self.segment_id,
3398 self.cap_table,
3399 self.pointer,
3400 other,
3401 canonicalize,
3402 )?;
3403 }
3404 }
3405 Ok(())
3406 }
3407
3408 pub fn clear(&mut self) {
3409 unsafe {
3410 wire_helpers::zero_object(self.arena, self.segment_id, self.pointer);
3411 ptr::write_bytes(self.pointer, 0, 1);
3412 }
3413 }
3414
3415 pub fn as_reader(&self) -> PointerReader<'_> {
3416 PointerReader {
3417 arena: self.arena.as_reader(),
3418 segment_id: self.segment_id,
3419 cap_table: self.cap_table.into_reader(),
3420 pointer: self.pointer,
3421 nesting_limit: 0x7fffffff,
3422 }
3423 }
3424
3425 pub fn into_reader(self) -> PointerReader<'a> {
3426 PointerReader {
3427 arena: self.arena.as_reader(),
3428 segment_id: self.segment_id,
3429 cap_table: self.cap_table.into_reader(),
3430 pointer: self.pointer,
3431 nesting_limit: 0x7fffffff,
3432 }
3433 }
3434}
3435
3436#[derive(Clone, Copy)]
3437pub struct StructReader<'a> {
3438 arena: &'a dyn ReaderArena,
3439 cap_table: CapTableReader,
3440 data: *const u8,
3441 pointers: *const WirePointer,
3442 segment_id: u32,
3443 data_size: BitCount32,
3444 pointer_count: WirePointerCount16,
3445 nesting_limit: i32,
3446}
3447
3448impl<'a> StructReader<'a> {
3449 pub(crate) fn new_default<'b>() -> StructReader<'b> {
3450 StructReader {
3451 arena: &NULL_ARENA,
3452 segment_id: 0,
3453 cap_table: Default::default(),
3454 data: ptr::null(),
3455 pointers: ptr::null(),
3456 data_size: 0,
3457 pointer_count: 0,
3458 nesting_limit: 0x7fffffff,
3459 }
3460 }
3461
3462 pub fn imbue(&mut self, cap_table: CapTableReader) {
3463 self.cap_table = cap_table
3464 }
3465
3466 pub(crate) fn get_data_section_size(&self) -> BitCount32 {
3467 self.data_size
3468 }
3469
3470 pub(crate) fn get_pointer_section_size(&self) -> WirePointerCount16 {
3471 self.pointer_count
3472 }
3473
3474 pub(crate) fn get_pointer_section_as_list(&self) -> ListReader<'a> {
3475 ListReader {
3476 arena: self.arena,
3477 segment_id: self.segment_id,
3478 cap_table: self.cap_table,
3479 ptr: self.pointers as *const _,
3480 element_count: u32::from(self.pointer_count),
3481 element_size: ElementSize::Pointer,
3482 step: BitCount32::try_from(BITS_PER_WORD).unwrap(),
3483 struct_data_size: 0,
3484 struct_pointer_count: 0,
3485 nesting_limit: self.nesting_limit,
3486 }
3487 }
3488
3489 pub(crate) fn get_data_section_as_blob(&self) -> &'a [u8] {
3490 if self.data_size == 0 {
3491 &[]
3494 } else {
3495 unsafe {
3496 ::core::slice::from_raw_parts(self.data, self.data_size as usize / BITS_PER_BYTE)
3497 }
3498 }
3499 }
3500
3501 #[inline]
3502 pub fn get_data_field<T: Primitive + zero::Zero>(&self, offset: ElementCount) -> T {
3503 if offset
3507 .checked_add(1)
3508 .and_then(|o| o.checked_mul(bits_per_element::<T>()))
3509 .is_some_and(|end_bits| end_bits <= self.data_size as usize)
3510 {
3511 let dwv: *const <T as Primitive>::Raw = self.data as *const _;
3512 unsafe { <T as Primitive>::get(&*dwv.add(offset)) }
3513 } else {
3514 T::zero()
3515 }
3516 }
3517
3518 #[inline]
3519 pub fn get_bool_field(&self, offset: ElementCount) -> bool {
3520 let boffset: BitCount32 = BitCount32::try_from(offset).unwrap();
3521 if boffset < self.data_size {
3522 unsafe {
3523 let b: *const u8 = self.data.add(offset / BITS_PER_BYTE);
3524 ((*b) & (1u8 << (boffset % u32::try_from(BITS_PER_BYTE).unwrap()) as usize)) != 0
3525 }
3526 } else {
3527 false
3528 }
3529 }
3530
3531 #[inline]
3532 pub fn get_data_field_mask<T: Primitive + zero::Zero + Mask>(
3533 &self,
3534 offset: ElementCount,
3535 mask: <T as Mask>::T,
3536 ) -> T {
3537 Mask::mask(self.get_data_field(offset), mask)
3538 }
3539
3540 #[inline]
3541 pub fn get_bool_field_mask(&self, offset: ElementCount, mask: bool) -> bool {
3542 self.get_bool_field(offset) ^ mask
3543 }
3544
3545 #[inline]
3546 pub fn get_pointer_field(&self, ptr_index: WirePointerCount) -> PointerReader<'a> {
3547 if ptr_index < self.pointer_count as WirePointerCount {
3548 PointerReader {
3549 arena: self.arena,
3550 segment_id: self.segment_id,
3551 cap_table: self.cap_table,
3552 pointer: unsafe { self.pointers.add(ptr_index) },
3553 nesting_limit: self.nesting_limit,
3554 }
3555 } else {
3556 PointerReader::new_default()
3557 }
3558 }
3559
3560 #[inline]
3561 pub fn is_pointer_field_null(&self, ptr_index: WirePointerCount) -> bool {
3562 self.get_pointer_field(ptr_index).is_null()
3563 }
3564
3565 pub fn total_size(&self) -> Result<MessageSize> {
3566 let mut result = MessageSize {
3567 word_count: u64::from(wire_helpers::round_bits_up_to_words(u64::from(
3568 self.data_size,
3569 ))) + u64::from(self.pointer_count) * WORDS_PER_POINTER as u64,
3570 cap_count: 0,
3571 };
3572
3573 for i in 0..self.pointer_count as usize {
3574 unsafe {
3575 result += wire_helpers::total_size(
3576 self.arena,
3577 self.segment_id,
3578 self.pointers.add(i),
3579 self.nesting_limit,
3580 )?;
3581 }
3582 }
3583
3584 Ok(result)
3587 }
3588
3589 fn get_location(&self) -> *const u8 {
3590 self.data
3591 }
3592
3593 pub fn is_canonical(
3594 &self,
3595 read_head: &Cell<*const u8>,
3596 ptr_head: &Cell<*const u8>,
3597 data_trunc: &mut bool,
3598 ptr_trunc: &mut bool,
3599 ) -> Result<bool> {
3600 if self.get_location() != read_head.get() {
3601 return Ok(false);
3602 }
3603
3604 if self.get_data_section_size() % u32::try_from(BITS_PER_WORD).unwrap() != 0 {
3605 return Ok(false);
3607 }
3608
3609 let data_size = self.get_data_section_size() / u32::try_from(BITS_PER_WORD).unwrap();
3610
3611 if data_size != 0 {
3613 *data_trunc = self.get_data_field::<u64>((data_size - 1) as usize) != 0;
3614 } else {
3615 *data_trunc = true;
3616 }
3617
3618 if self.pointer_count != 0 {
3619 *ptr_trunc = !self
3620 .get_pointer_field(self.pointer_count as usize - 1)
3621 .is_null();
3622 } else {
3623 *ptr_trunc = true;
3624 }
3625
3626 read_head.set(unsafe {
3627 read_head
3628 .get()
3629 .add((data_size as usize + self.pointer_count as usize) * BYTES_PER_WORD)
3630 });
3631
3632 for ptr_idx in 0..self.pointer_count {
3633 if !self
3634 .get_pointer_field(ptr_idx as usize)
3635 .is_canonical(ptr_head)?
3636 {
3637 return Ok(false);
3638 }
3639 }
3640
3641 Ok(true)
3642 }
3643}
3644
3645pub struct StructBuilder<'a> {
3646 arena: &'a mut dyn BuilderArena,
3647 cap_table: CapTableBuilder,
3648 data: *mut u8,
3649 pointers: *mut WirePointer,
3650 segment_id: u32,
3651 data_size: BitCount32,
3652 pointer_count: WirePointerCount16,
3653}
3654
3655impl<'a> StructBuilder<'a> {
3656 #[inline]
3657 pub fn reborrow(&mut self) -> StructBuilder<'_> {
3658 StructBuilder {
3659 arena: self.arena,
3660 ..*self
3661 }
3662 }
3663
3664 pub fn as_reader(&self) -> StructReader<'_> {
3665 StructReader {
3666 arena: self.arena.as_reader(),
3667 cap_table: self.cap_table.into_reader(),
3668 data: self.data,
3669 pointers: self.pointers,
3670 pointer_count: self.pointer_count,
3671 segment_id: self.segment_id,
3672 data_size: self.data_size,
3673 nesting_limit: 0x7fffffff,
3674 }
3675 }
3676
3677 pub fn into_reader(self) -> StructReader<'a> {
3678 StructReader {
3679 arena: self.arena.as_reader(),
3680 cap_table: self.cap_table.into_reader(),
3681 data: self.data,
3682 pointers: self.pointers,
3683 pointer_count: self.pointer_count,
3684 segment_id: self.segment_id,
3685 data_size: self.data_size,
3686 nesting_limit: 0x7fffffff,
3687 }
3688 }
3689
3690 pub fn imbue(&mut self, cap_table: CapTableBuilder) {
3691 self.cap_table = cap_table
3692 }
3693
3694 #[inline]
3695 pub fn set_data_field<T: Primitive>(&self, offset: ElementCount, value: T) {
3696 let ptr: *mut <T as Primitive>::Raw = self.data as *mut _;
3697 unsafe { <T as Primitive>::set(&mut *ptr.add(offset), value) }
3698 }
3699
3700 #[inline]
3701 pub fn set_data_field_mask<T: Primitive + Mask>(
3702 &self,
3703 offset: ElementCount,
3704 value: T,
3705 mask: <T as Mask>::T,
3706 ) {
3707 self.set_data_field(offset, Mask::mask(value, mask));
3708 }
3709
3710 #[inline]
3711 pub fn get_data_field<T: Primitive>(&self, offset: ElementCount) -> T {
3712 let ptr: *const <T as Primitive>::Raw = self.data as *const _;
3713 unsafe { <T as Primitive>::get(&*ptr.add(offset)) }
3714 }
3715
3716 #[inline]
3717 pub fn get_data_field_mask<T: Primitive + Mask>(
3718 &self,
3719 offset: ElementCount,
3720 mask: <T as Mask>::T,
3721 ) -> T {
3722 Mask::mask(self.get_data_field(offset), mask)
3723 }
3724
3725 #[inline]
3726 pub fn set_bool_field(&self, offset: ElementCount, value: bool) {
3727 let boffset: BitCount0 = offset;
3730 let b = unsafe { self.data.add(boffset / BITS_PER_BYTE) };
3731 let bitnum = boffset % BITS_PER_BYTE;
3732 unsafe { (*b) = ((*b) & !(1 << bitnum)) | (u8::from(value) << bitnum) }
3733 }
3734
3735 #[inline]
3736 pub fn set_bool_field_mask(&self, offset: ElementCount, value: bool, mask: bool) {
3737 self.set_bool_field(offset, value ^ mask);
3738 }
3739
3740 #[inline]
3741 pub fn get_bool_field(&self, offset: ElementCount) -> bool {
3742 let boffset: BitCount0 = offset;
3743 let b = unsafe { self.data.add(boffset / BITS_PER_BYTE) };
3744 unsafe { ((*b) & (1 << (boffset % BITS_PER_BYTE))) != 0 }
3745 }
3746
3747 #[inline]
3748 pub fn get_bool_field_mask(&self, offset: ElementCount, mask: bool) -> bool {
3749 self.get_bool_field(offset) ^ mask
3750 }
3751
3752 #[inline]
3753 pub fn get_pointer_field(self, ptr_index: WirePointerCount) -> PointerBuilder<'a> {
3754 PointerBuilder {
3755 arena: self.arena,
3756 segment_id: self.segment_id,
3757 cap_table: self.cap_table,
3758 pointer: unsafe { self.pointers.add(ptr_index) },
3759 }
3760 }
3761
3762 #[inline]
3763 pub fn is_pointer_field_null(&self, ptr_index: WirePointerCount) -> bool {
3764 unsafe { (*self.pointers.add(ptr_index)).is_null() }
3765 }
3766
3767 pub(crate) fn copy_content_from(&mut self, other: &StructReader) -> Result<()> {
3768 use core::cmp::min;
3769 let shared_data_size = min(self.data_size, other.data_size);
3771 let shared_pointer_count = min(self.pointer_count, other.pointer_count);
3772
3773 if (shared_data_size > 0 && other.data == self.data)
3774 || (shared_pointer_count > 0 && other.pointers == self.pointers)
3775 {
3776 if !((shared_data_size == 0 || other.data == self.data)
3779 && (shared_pointer_count == 0 || other.pointers == self.pointers))
3780 {
3781 return Err(Error::from_kind(
3782 ErrorKind::OnlyOneOfTheSectionPointersIsPointingToOurself,
3783 ));
3784 }
3785
3786 return Ok(());
3788 }
3789
3790 unsafe {
3791 if self.data_size > shared_data_size {
3792 if self.data_size == 1 {
3795 self.set_bool_field(0, false);
3796 } else {
3797 let unshared = self.data.add(
3798 usize::try_from(shared_data_size / u32::try_from(BITS_PER_BYTE).unwrap())
3799 .unwrap(),
3800 );
3801 ptr::write_bytes(
3802 unshared,
3803 0,
3804 usize::try_from(
3805 (self.data_size - shared_data_size)
3806 / u32::try_from(BITS_PER_BYTE).unwrap(),
3807 )
3808 .unwrap(),
3809 );
3810 }
3811 }
3812
3813 if shared_data_size == 1 {
3815 self.set_bool_field(0, other.get_bool_field(0));
3816 } else {
3817 wire_helpers::copy_nonoverlapping_check_zero(
3818 other.data,
3819 self.data,
3820 (shared_data_size / u32::try_from(BITS_PER_BYTE).unwrap()) as usize,
3821 );
3822 }
3823
3824 for i in 0..self.pointer_count as usize {
3826 wire_helpers::zero_object(
3827 self.arena,
3828 self.segment_id,
3829 self.pointers.add(i) as *mut _,
3830 );
3831 }
3832 ptr::write_bytes(self.pointers, 0u8, self.pointer_count as usize);
3833
3834 for i in 0..shared_pointer_count as usize {
3835 wire_helpers::deep_copy_pointee(
3836 self.arena,
3837 self.segment_id,
3838 self.cap_table,
3839 self.pointers.add(i),
3840 other.get_pointer_field(i),
3841 false,
3842 )?;
3843 }
3844 }
3845
3846 Ok(())
3847 }
3848}
3849
3850#[derive(Clone, Copy)]
3851pub struct ListReader<'a> {
3852 arena: &'a dyn ReaderArena,
3853 cap_table: CapTableReader,
3854 ptr: *const u8,
3855 segment_id: u32,
3856 element_count: ElementCount32,
3857 step: BitCount32,
3858 struct_data_size: BitCount32,
3859 nesting_limit: i32,
3860 struct_pointer_count: WirePointerCount16,
3861 element_size: ElementSize,
3862}
3863
3864impl<'a> ListReader<'a> {
3865 pub(crate) fn new_default<'b>() -> ListReader<'b> {
3866 ListReader {
3867 arena: &NULL_ARENA,
3868 segment_id: 0,
3869 cap_table: Default::default(),
3870 ptr: ptr::null(),
3871 element_count: 0,
3872 element_size: ElementSize::Void,
3873 step: 0,
3874 struct_data_size: 0,
3875 struct_pointer_count: 0,
3876 nesting_limit: 0x7fffffff,
3877 }
3878 }
3879
3880 pub fn imbue(&mut self, cap_table: CapTableReader) {
3881 self.cap_table = cap_table
3882 }
3883
3884 #[inline]
3885 pub fn len(&self) -> ElementCount32 {
3886 self.element_count
3887 }
3888
3889 pub fn is_empty(&self) -> bool {
3890 self.len() == 0
3891 }
3892
3893 pub(crate) fn get_step_size_in_bits(&self) -> u32 {
3894 self.step
3895 }
3896
3897 pub(crate) fn get_element_size(&self) -> ElementSize {
3898 self.element_size
3899 }
3900
3901 pub(crate) fn into_raw_bytes(self) -> &'a [u8] {
3902 if self.element_count == 0 {
3903 &[]
3906 } else {
3907 let num_bytes = wire_helpers::round_bits_up_to_bytes(
3908 u64::from(self.step) * u64::from(self.element_count),
3909 ) as usize;
3910 unsafe { ::core::slice::from_raw_parts(self.ptr, num_bytes) }
3911 }
3912 }
3913
3914 #[inline]
3915 pub(crate) fn get_struct_element(&self, index: ElementCount32) -> StructReader<'a> {
3916 assert!(index < self.element_count);
3917 let index_byte =
3918 usize::try_from((u64::from(index) * u64::from(self.step)) / BITS_PER_BYTE as u64)
3919 .unwrap();
3920
3921 let struct_data: *const u8 = unsafe { self.ptr.add(index_byte) };
3922
3923 let struct_pointers: *const WirePointer =
3924 unsafe { struct_data.add(self.struct_data_size as usize / BITS_PER_BYTE) as *const _ };
3925
3926 StructReader {
3927 arena: self.arena,
3928 segment_id: self.segment_id,
3929 cap_table: self.cap_table,
3930 data: struct_data,
3931 pointers: struct_pointers,
3932 data_size: self.struct_data_size,
3933 pointer_count: self.struct_pointer_count,
3934 nesting_limit: self.nesting_limit - 1,
3935 }
3936 }
3937
3938 #[inline]
3939 pub(crate) fn get_pointer_element(self, index: ElementCount32) -> PointerReader<'a> {
3940 assert!(index < self.element_count);
3941 let offset = usize::try_from(
3942 self.struct_data_size as u64 / BITS_PER_BYTE as u64
3943 + u64::from(index) * u64::from(self.step) / BITS_PER_BYTE as u64,
3944 )
3945 .unwrap();
3946 PointerReader {
3947 arena: self.arena,
3948 segment_id: self.segment_id,
3949 cap_table: self.cap_table,
3950 pointer: unsafe { self.ptr.add(offset) } as *const _,
3951 nesting_limit: self.nesting_limit,
3952 }
3953 }
3954
3955 pub(crate) unsafe fn is_canonical(
3956 &self,
3957 read_head: &Cell<*const u8>,
3958 reff: *const WirePointer,
3959 ) -> Result<bool> {
3960 match self.element_size {
3961 ElementSize::InlineComposite => {
3962 read_head.set(unsafe { read_head.get().add(BYTES_PER_WORD) }); if !core::ptr::eq(self.ptr, read_head.get()) {
3964 return Ok(false);
3965 }
3966 if self.struct_data_size % u32::try_from(BITS_PER_WORD).unwrap() != 0 {
3967 return Ok(false);
3968 }
3969 let struct_size = (self.struct_data_size / u32::try_from(BITS_PER_WORD).unwrap())
3970 + u32::from(self.struct_pointer_count);
3971 let word_count = unsafe { (*reff).list_inline_composite_word_count() };
3972 if struct_size * self.element_count != word_count {
3973 return Ok(false);
3974 }
3975 if struct_size == 0 {
3976 return Ok(true);
3977 }
3978 let list_end = unsafe {
3979 read_head
3980 .get()
3981 .add((self.element_count * struct_size) as usize * BYTES_PER_WORD)
3982 };
3983 let pointer_head = Cell::new(list_end);
3984 let mut list_data_trunc = false;
3985 let mut list_ptr_trunc = false;
3986 for idx in 0..self.element_count {
3987 let mut data_trunc = false;
3988 let mut ptr_trunc = false;
3989 if !self.get_struct_element(idx).is_canonical(
3990 read_head,
3991 &pointer_head,
3992 &mut data_trunc,
3993 &mut ptr_trunc,
3994 )? {
3995 return Ok(false);
3996 }
3997 list_data_trunc |= data_trunc;
3998 list_ptr_trunc |= ptr_trunc;
3999 }
4000 assert_eq!(read_head.get(), list_end);
4001 read_head.set(pointer_head.get());
4002 Ok(list_data_trunc && list_ptr_trunc)
4003 }
4004 ElementSize::Pointer => {
4005 if !core::ptr::eq(self.ptr, read_head.get()) {
4006 return Ok(false);
4007 }
4008 read_head.set(unsafe {
4009 read_head
4010 .get()
4011 .add(self.element_count as usize * BYTES_PER_WORD)
4012 });
4013 for idx in 0..self.element_count {
4014 if !self.get_pointer_element(idx).is_canonical(read_head)? {
4015 return Ok(false);
4016 }
4017 }
4018 Ok(true)
4019 }
4020 element_size => {
4021 if !core::ptr::eq(self.ptr, read_head.get()) {
4022 return Ok(false);
4023 }
4024 let bit_size =
4025 u64::from(self.element_count) * u64::from(data_bits_per_element(element_size));
4026 let mut word_size = bit_size / BITS_PER_WORD as u64;
4027 if bit_size % BITS_PER_WORD as u64 != 0 {
4028 word_size += 1
4029 }
4030
4031 let byte_size = bit_size / BITS_PER_BYTE as u64;
4032 let mut byte_read_head: *const u8 = read_head.get();
4033 byte_read_head = unsafe { byte_read_head.add(usize::try_from(byte_size).unwrap()) };
4034 let read_head_end = unsafe {
4035 read_head
4036 .get()
4037 .add(usize::try_from(word_size).unwrap() * BYTES_PER_WORD)
4038 };
4039
4040 let leftover_bits = u8::try_from(bit_size % BITS_PER_BYTE as u64).unwrap();
4041 if leftover_bits > 0 {
4042 let mask: u8 = !((1 << leftover_bits) - 1);
4043 let partial_byte = unsafe { *byte_read_head };
4044
4045 if partial_byte & mask != 0 {
4046 return Ok(false);
4047 }
4048 byte_read_head = unsafe { byte_read_head.add(1) };
4049 }
4050
4051 while byte_read_head != read_head_end {
4052 if unsafe { *byte_read_head } != 0 {
4053 return Ok(false);
4054 }
4055 byte_read_head = unsafe { byte_read_head.add(1) };
4056 }
4057
4058 read_head.set(read_head_end);
4059 Ok(true)
4060 }
4061 }
4062 }
4063}
4064
4065pub struct ListBuilder<'a> {
4066 arena: &'a mut dyn BuilderArena,
4067 cap_table: CapTableBuilder,
4068 ptr: *mut u8,
4069 segment_id: u32,
4070 element_count: ElementCount32,
4071 step: BitCount32,
4072 struct_data_size: BitCount32,
4073 struct_pointer_count: WirePointerCount16,
4074 element_size: ElementSize,
4075}
4076
4077impl<'a> ListBuilder<'a> {
4078 #[inline]
4079 pub(crate) fn new_default(arena: &mut dyn BuilderArena) -> ListBuilder<'_> {
4080 ListBuilder {
4081 arena,
4082 segment_id: 0,
4083 cap_table: Default::default(),
4084 ptr: ptr::null_mut(),
4085 element_count: 0,
4086 element_size: ElementSize::Void,
4087 step: 0,
4088 struct_data_size: 0,
4089 struct_pointer_count: 0,
4090 }
4091 }
4092
4093 pub fn into_reader(self) -> ListReader<'a> {
4094 ListReader {
4095 arena: self.arena.as_reader(),
4096 segment_id: self.segment_id,
4097 cap_table: self.cap_table.into_reader(),
4098 ptr: self.ptr as *const _,
4099 element_count: self.element_count,
4100 element_size: self.element_size,
4101 step: self.step,
4102 struct_data_size: self.struct_data_size,
4103 struct_pointer_count: self.struct_pointer_count,
4104 nesting_limit: 0x7fffffff,
4105 }
4106 }
4107
4108 #[inline]
4109 pub fn reborrow(&mut self) -> ListBuilder<'_> {
4110 ListBuilder {
4111 arena: self.arena,
4112 ..*self
4113 }
4114 }
4115
4116 pub fn imbue(&mut self, cap_table: CapTableBuilder) {
4117 self.cap_table = cap_table
4118 }
4119
4120 #[inline]
4121 pub fn len(&self) -> ElementCount32 {
4122 self.element_count
4123 }
4124
4125 pub fn is_empty(&self) -> bool {
4126 self.len() == 0
4127 }
4128
4129 #[inline]
4130 pub(crate) fn get_struct_element(self, index: ElementCount32) -> StructBuilder<'a> {
4131 assert!(index < self.element_count);
4132 let index_byte =
4133 usize::try_from((u64::from(index) * u64::from(self.step)) / BITS_PER_BYTE as u64)
4134 .unwrap();
4135 let struct_data = unsafe { self.ptr.add(index_byte) };
4136 let struct_pointers =
4137 unsafe { struct_data.add((self.struct_data_size as usize) / BITS_PER_BYTE) as *mut _ };
4138 StructBuilder {
4139 arena: self.arena,
4140 segment_id: self.segment_id,
4141 cap_table: self.cap_table,
4142 data: struct_data,
4143 pointers: struct_pointers,
4144 data_size: self.struct_data_size,
4145 pointer_count: self.struct_pointer_count,
4146 }
4147 }
4148
4149 pub(crate) fn get_element_size(&self) -> ElementSize {
4150 self.element_size
4151 }
4152
4153 #[inline]
4154 pub fn get_pointer_element(self, index: ElementCount32) -> PointerBuilder<'a> {
4155 assert!(index < self.element_count);
4156 let offset =
4157 usize::try_from(u64::from(index) * u64::from(self.step) / BITS_PER_BYTE as u64)
4158 .unwrap();
4159 PointerBuilder {
4160 arena: self.arena,
4161 segment_id: self.segment_id,
4162 cap_table: self.cap_table,
4163 pointer: unsafe { self.ptr.add(offset) } as *mut _,
4164 }
4165 }
4166
4167 pub(crate) fn as_raw_bytes(&self) -> &'a mut [u8] {
4168 if self.element_count == 0 {
4169 &mut []
4172 } else {
4173 let num_bytes = wire_helpers::round_bits_up_to_bytes(
4174 u64::from(self.step) * u64::from(self.element_count),
4175 ) as usize;
4176 unsafe { ::core::slice::from_raw_parts_mut(self.ptr, num_bytes) }
4177 }
4178 }
4179}
4180
4181pub trait PrimitiveElement {
4185 fn get(list_reader: &ListReader, index: ElementCount32) -> Self;
4187
4188 fn get_from_builder(list_builder: &ListBuilder, index: ElementCount32) -> Self;
4190
4191 fn set(list_builder: &ListBuilder, index: ElementCount32, value: Self);
4193
4194 fn element_size() -> ElementSize;
4196}
4197
4198impl<T: Primitive> PrimitiveElement for T {
4199 #[inline]
4200 fn get(list_reader: &ListReader, index: ElementCount32) -> Self {
4201 assert!(index < list_reader.len());
4202 let offset =
4203 usize::try_from(u64::from(index) * u64::from(list_reader.step) / BITS_PER_BYTE as u64)
4204 .unwrap();
4205 unsafe {
4206 let ptr: *const u8 = list_reader.ptr.add(offset);
4207 <Self as Primitive>::get(&*(ptr as *const <Self as Primitive>::Raw))
4208 }
4209 }
4210
4211 #[inline]
4212 fn get_from_builder(list_builder: &ListBuilder, index: ElementCount32) -> Self {
4213 assert!(index < list_builder.element_count);
4214 let offset =
4215 usize::try_from(u64::from(index) * u64::from(list_builder.step) / BITS_PER_BYTE as u64)
4216 .unwrap();
4217 unsafe {
4218 let ptr: *mut <Self as Primitive>::Raw = list_builder.ptr.add(offset) as *mut _;
4219 <Self as Primitive>::get(&*ptr)
4220 }
4221 }
4222
4223 #[inline]
4224 fn set(list_builder: &ListBuilder, index: ElementCount32, value: Self) {
4225 assert!(index < list_builder.element_count);
4226 let offset =
4227 usize::try_from(u64::from(index) * u64::from(list_builder.step) / BITS_PER_BYTE as u64)
4228 .unwrap();
4229 unsafe {
4230 let ptr: *mut <Self as Primitive>::Raw = list_builder.ptr.add(offset) as *mut _;
4231 <Self as Primitive>::set(&mut *ptr, value);
4232 }
4233 }
4234
4235 fn element_size() -> ElementSize {
4236 match mem::size_of::<Self>() {
4237 0 => Void,
4238 1 => Byte,
4239 2 => TwoBytes,
4240 4 => FourBytes,
4241 8 => EightBytes,
4242 _ => unreachable!(),
4243 }
4244 }
4245}
4246
4247impl PrimitiveElement for bool {
4248 #[inline]
4249 fn get(list: &ListReader, index: ElementCount32) -> Self {
4250 assert!(index < list.len());
4251 let bindex = u64::from(index) * u64::from(list.step);
4252 unsafe {
4253 let b: *const u8 = list
4254 .ptr
4255 .add(usize::try_from(bindex / BITS_PER_BYTE as u64).unwrap());
4256 ((*b) & (1 << (bindex % BITS_PER_BYTE as u64))) != 0
4257 }
4258 }
4259 #[inline]
4260 fn get_from_builder(list: &ListBuilder, index: ElementCount32) -> Self {
4261 assert!(index < list.len());
4262 let bindex = u64::from(index) * u64::from(list.step);
4263 let b = unsafe {
4264 list.ptr
4265 .add(usize::try_from(bindex / BITS_PER_BYTE as u64).unwrap())
4266 };
4267 unsafe { ((*b) & (1 << (bindex % BITS_PER_BYTE as u64))) != 0 }
4268 }
4269 #[inline]
4270 fn set(list: &ListBuilder, index: ElementCount32, value: Self) {
4271 assert!(index < list.len());
4272 let bindex = u64::from(index) * u64::from(list.step);
4273 let b = unsafe {
4274 list.ptr
4275 .add(usize::try_from(bindex / BITS_PER_BYTE as u64).unwrap())
4276 };
4277
4278 let bitnum = bindex % BITS_PER_BYTE as u64;
4279 unsafe { (*b) = ((*b) & !(1 << bitnum)) | (u8::from(value) << bitnum) }
4280 }
4281 fn element_size() -> ElementSize {
4282 Bit
4283 }
4284}
4285
4286impl PrimitiveElement for () {
4287 #[inline]
4288 fn get(_list: &ListReader, _index: ElementCount32) {}
4289
4290 #[inline]
4291 fn get_from_builder(_list: &ListBuilder, _index: ElementCount32) {}
4292
4293 #[inline]
4294 fn set(_list: &ListBuilder, _index: ElementCount32, _value: ()) {}
4295
4296 fn element_size() -> ElementSize {
4297 Void
4298 }
4299}