1use crate::bitfields::{HeaderFields, PayloadFields};
8use crate::block_index::BlockIndex;
9use crate::block_type::BlockType;
10use crate::container::{ReadBytes, WriteBytes};
11use crate::error::Error;
12use crate::{constants, utils};
13use byteorder::{ByteOrder, LittleEndian};
14use num_derive::FromPrimitive;
15use num_traits::FromPrimitive;
16use std::cmp::min;
17use std::marker::PhantomData;
18use std::ops::{Deref, DerefMut};
19use std::sync::atomic::{Ordering, fence};
20
21pub use diagnostics_hierarchy::ArrayFormat;
22
23#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
25#[repr(u8)]
26pub enum LinkNodeDisposition {
27 Child = 0,
28 Inline = 1,
29}
30
31#[derive(Debug, PartialEq, Eq, FromPrimitive)]
33#[repr(u8)]
34pub enum PropertyFormat {
35 String = 0,
36 Bytes = 1,
37 StringReference = 2,
38}
39
40#[derive(Debug, Clone)]
42pub struct Block<T, Kind> {
43 pub(crate) index: BlockIndex,
44 pub(crate) container: T,
45 _phantom: PhantomData<Kind>,
46}
47
48impl<T: Deref<Target = Q>, Q, K> Block<T, K> {
49 #[inline]
51 pub(crate) fn new(container: T, index: BlockIndex) -> Self {
52 Block { container, index, _phantom: PhantomData }
53 }
54}
55
56pub trait BlockAccessorExt: ReadBytes + Sized {
57 #[inline]
58 fn maybe_block_at<K: BlockKind>(&self, index: BlockIndex) -> Option<Block<&Self, K>> {
59 let block = Block::new(self, index);
60 let block_type = HeaderFields::block_type(&block);
61 if block_type != K::block_type() as u8 {
62 return None;
63 }
64 Some(block)
65 }
66
67 #[cfg_attr(debug_assertions, track_caller)]
68 #[inline]
69 fn block_at_unchecked<K: BlockKind>(&self, index: BlockIndex) -> Block<&Self, K> {
70 Block::new(self, index)
71 }
74
75 #[inline]
76 fn block_at(&self, index: BlockIndex) -> Block<&Self, Unknown> {
77 Block::new(self, index)
78 }
79}
80
81pub trait BlockAccessorMutExt: WriteBytes + ReadBytes + Sized {
82 #[inline]
83 fn maybe_block_at_mut<K: BlockKind>(
84 &mut self,
85 index: BlockIndex,
86 ) -> Option<Block<&mut Self, K>> {
87 let block = Block::new(self, index);
88 let block_type = HeaderFields::block_type(&block);
89 if block_type != K::block_type() as u8 {
90 return None;
91 }
92 Some(block)
93 }
94
95 #[inline]
96 fn block_at_unchecked_mut<K: BlockKind>(&mut self, index: BlockIndex) -> Block<&mut Self, K> {
97 Block::new(self, index)
98 }
99
100 #[inline]
101 fn block_at_mut(&mut self, index: BlockIndex) -> Block<&mut Self, Unknown> {
102 Block::new(self, index)
103 }
104}
105
106impl<T> BlockAccessorExt for T where T: ReadBytes {}
107impl<T> BlockAccessorMutExt for T where T: WriteBytes + ReadBytes {}
108
109mod private {
110 pub trait Sealed {}
111}
112
113pub trait BlockKind: private::Sealed {
114 fn block_type() -> BlockType;
115}
116
117macro_rules! block_kind {
118 ([$(($name:ident, $block_type:ident)),*]) => {
119 $(
120 #[derive(Copy, Clone, Debug)]
121 pub struct $name;
122 impl BlockKind for $name {
123 fn block_type() -> BlockType {
124 BlockType::$block_type
125 }
126 }
127 impl private::Sealed for $name {}
128 )*
129 }
130}
131
132block_kind!([
133 (Header, Header),
134 (Double, DoubleValue),
135 (Int, IntValue),
136 (Uint, UintValue),
137 (Bool, BoolValue),
138 (Buffer, BufferValue),
139 (Extent, Extent),
140 (StringRef, StringReference),
141 (Link, LinkValue),
142 (Node, NodeValue),
143 (Free, Free),
144 (Tombstone, Tombstone),
145 (Reserved, Reserved),
146 (Name, Name)
147]);
148
149#[derive(Copy, Clone, Debug)]
150pub struct Unknown;
151impl private::Sealed for Unknown {}
152impl BlockKind for Unknown {
153 #[track_caller]
154 fn block_type() -> BlockType {
155 panic!("implementation must not call into Unknown::block_type()")
156 }
157}
158
159#[derive(Copy, Clone, Debug)]
160pub struct Array<T>(PhantomData<T>);
161impl<T> private::Sealed for Array<T> {}
162impl<T: ArraySlotKind> BlockKind for Array<T> {
163 fn block_type() -> BlockType {
164 BlockType::ArrayValue
165 }
166}
167
168pub trait ValueBlockKind: BlockKind {}
169
170macro_rules! impl_value_block {
171 ([$($name:ident),*]) => {
172 $(
173 impl ValueBlockKind for $name {}
174 )*
175 }
176}
177
178impl_value_block!([Node, Int, Uint, Double, Buffer, Link, Bool]);
179impl<T: ArraySlotKind> ValueBlockKind for Array<T> {}
180
181pub trait ArraySlotKind: BlockKind {
182 fn array_entry_type_size() -> usize;
183}
184
185impl ArraySlotKind for Double {
186 fn array_entry_type_size() -> usize {
187 std::mem::size_of::<f64>()
188 }
189}
190
191impl ArraySlotKind for Int {
192 fn array_entry_type_size() -> usize {
193 std::mem::size_of::<i64>()
194 }
195}
196
197impl ArraySlotKind for Uint {
198 fn array_entry_type_size() -> usize {
199 std::mem::size_of::<u64>()
200 }
201}
202
203impl ArraySlotKind for StringRef {
204 fn array_entry_type_size() -> usize {
205 std::mem::size_of::<u32>()
206 }
207}
208
209impl ArraySlotKind for Unknown {
210 #[track_caller]
211 fn array_entry_type_size() -> usize {
212 panic!("Implementation must not get the size of Unknown");
213 }
214}
215
216impl<T: Deref<Target = Q>, Q: ReadBytes, K: BlockKind> Block<T, K> {
217 pub fn index(&self) -> BlockIndex {
219 self.index
220 }
221
222 pub fn order(&self) -> u8 {
224 HeaderFields::order(self)
225 }
226
227 pub fn block_type(&self) -> Option<BlockType> {
229 let block_type = self.block_type_raw();
230 BlockType::from_u8(block_type)
231 }
232
233 pub fn block_type_raw(&self) -> u8 {
235 HeaderFields::block_type(self)
236 }
237
238 pub(crate) fn payload_offset(&self) -> usize {
240 self.index.offset() + constants::HEADER_SIZE_BYTES
241 }
242
243 pub(crate) fn header_offset(&self) -> usize {
245 self.index.offset()
246 }
247}
248
249impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Unknown> {
250 pub fn cast<K: BlockKind>(self) -> Option<Block<T, K>> {
251 let block_type = HeaderFields::block_type(&self);
252 if block_type != K::block_type() as u8 {
253 return None;
254 }
255 Some(Block { container: self.container, index: self.index, _phantom: PhantomData })
256 }
257
258 pub fn cast_unchecked<K: BlockKind>(self) -> Block<T, K> {
259 Block { container: self.container, index: self.index, _phantom: PhantomData }
260 }
261}
262
263impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Array<Unknown>> {
264 pub fn cast_array<K: ArraySlotKind>(self) -> Option<Block<T, Array<K>>> {
265 let entry_type = self.entry_type()?;
266 if entry_type != K::block_type() {
267 return None;
268 }
269 Some(Block { container: self.container, index: self.index, _phantom: PhantomData })
270 }
271
272 pub fn cast_array_unchecked<K: BlockKind>(self) -> Block<T, Array<K>> {
273 Block { container: self.container, index: self.index, _phantom: PhantomData }
274 }
275}
276
277impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Header> {
278 pub fn magic_number(&self) -> u32 {
280 HeaderFields::header_magic(self)
281 }
282
283 pub fn version(&self) -> u32 {
285 HeaderFields::header_version(self)
286 }
287
288 pub fn generation_count(&self) -> u64 {
290 PayloadFields::value(self)
291 }
292
293 pub fn vmo_size(&self) -> Result<Option<u32>, Error> {
296 if self.order() != constants::HEADER_ORDER {
297 return Ok(None);
298 }
299 let offset = (self.index + 1).offset();
300 let value = self.container.get_value(offset).ok_or(Error::InvalidOffset(offset))?;
301 Ok(Some(value))
302 }
303
304 pub fn is_locked(&self) -> bool {
306 PayloadFields::value(self) & 1 == 1
307 }
308
309 #[doc(hidden)]
312 #[cfg_attr(debug_assertions, track_caller)]
313 pub fn check_locked(&self, value: bool) {
314 if cfg!(any(debug_assertions, test)) {
315 let generation_count = PayloadFields::value(self);
316 if (generation_count & 1 == 1) != value {
317 panic!("Expected lock state: {value}")
318 }
319 }
320 }
321}
322
323impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Double> {
324 pub fn value(&self) -> f64 {
326 f64::from_bits(PayloadFields::value(self))
327 }
328}
329
330impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Int> {
331 pub fn value(&self) -> i64 {
333 i64::from_le_bytes(PayloadFields::value(self).to_le_bytes())
334 }
335}
336
337impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Uint> {
338 pub fn value(&self) -> u64 {
340 PayloadFields::value(self)
341 }
342}
343
344impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Bool> {
345 pub fn value(&self) -> bool {
347 PayloadFields::value(self) != 0
348 }
349}
350
351impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Buffer> {
352 pub fn extent_index(&self) -> BlockIndex {
354 PayloadFields::property_extent_index(self).into()
355 }
356
357 pub fn total_length(&self) -> usize {
359 PayloadFields::property_total_length(self) as usize
360 }
361
362 pub fn format(&self) -> Option<PropertyFormat> {
364 let raw_format = PayloadFields::property_flags(self);
365 PropertyFormat::from_u8(raw_format)
366 }
367
368 pub fn format_raw(&self) -> u8 {
370 PayloadFields::property_flags(self)
371 }
372}
373
374impl<'a, T: Deref<Target = Q>, Q: ReadBytes + 'a> Block<T, StringRef> {
375 pub fn total_length(&self) -> usize {
377 PayloadFields::property_total_length(self) as usize
378 }
379
380 pub fn next_extent(&self) -> BlockIndex {
382 HeaderFields::extent_next_index(self).into()
383 }
384
385 pub fn reference_count(&self) -> u32 {
387 HeaderFields::string_reference_count(self)
388 }
389
390 pub fn inline_data(&'a self) -> Result<&'a [u8], Error> {
392 let max_len_inlined = utils::payload_size_for_order(self.order())
393 - constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES;
394 let length = self.total_length();
395 let offset = self.payload_offset() + constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES;
396 let bytes = self
397 .container
398 .get_slice_at(offset, min(length, max_len_inlined))
399 .ok_or(Error::InvalidOffset(offset))?;
400 Ok(bytes)
401 }
402}
403
404impl<'a, T: Deref<Target = Q>, Q: ReadBytes + 'a> Block<T, Extent> {
405 pub fn next_extent(&self) -> BlockIndex {
407 HeaderFields::extent_next_index(self).into()
408 }
409
410 pub fn contents(&'a self) -> Result<&'a [u8], Error> {
412 let length = utils::payload_size_for_order(self.order());
413 let offset = self.payload_offset();
414 self.container.get_slice_at(offset, length).ok_or(Error::InvalidOffset(offset))
415 }
416}
417
418impl<T: Deref<Target = Q>, Q: ReadBytes, S: ArraySlotKind> Block<T, Array<S>> {
419 pub fn format(&self) -> Option<ArrayFormat> {
421 let raw_flags = PayloadFields::array_flags(self);
422 ArrayFormat::from_u8(raw_flags)
423 }
424
425 pub fn slots(&self) -> usize {
427 PayloadFields::array_slots_count(self) as usize
428 }
429
430 pub fn capacity(&self) -> Option<usize> {
432 self.entry_type_size().map(|size| array_capacity(size, self.order()))
433 }
434
435 pub fn entry_type(&self) -> Option<BlockType> {
437 let array_type_raw = PayloadFields::array_entry_type(self);
438 BlockType::from_u8(array_type_raw).filter(|array_type| array_type.is_valid_for_array())
439 }
440
441 pub fn entry_type_raw(&self) -> u8 {
443 PayloadFields::array_entry_type(self)
444 }
445
446 pub fn entry_type_size(&self) -> Option<usize> {
447 self.entry_type().and_then(|entry_type| match entry_type {
448 BlockType::IntValue => Some(Int::array_entry_type_size()),
449 BlockType::UintValue => Some(Uint::array_entry_type_size()),
450 BlockType::DoubleValue => Some(Double::array_entry_type_size()),
451 BlockType::StringReference => Some(StringRef::array_entry_type_size()),
452 _ => None,
453 })
454 }
455}
456
457impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Array<StringRef>> {
458 pub fn get_string_index_at(&self, slot_index: usize) -> Option<BlockIndex> {
459 if slot_index >= self.slots() {
460 return None;
461 }
462 let offset = (self.index + 1).offset() + slot_index * StringRef::array_entry_type_size();
463 self.container.get_value(offset).map(BlockIndex::new)
464 }
465}
466
467impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Array<Int>> {
468 pub fn get(&self, slot_index: usize) -> Option<i64> {
470 if slot_index >= self.slots() {
471 return None;
472 }
473 let offset = (self.index + 1).offset() + slot_index * 8;
474 self.container.get_value(offset)
475 }
476}
477
478impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Array<Double>> {
479 pub fn get(&self, slot_index: usize) -> Option<f64> {
481 if slot_index >= self.slots() {
482 return None;
483 }
484 let offset = (self.index + 1).offset() + slot_index * 8;
485 self.container.get_value(offset)
486 }
487}
488
489impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Array<Uint>> {
490 pub fn get(&self, slot_index: usize) -> Option<u64> {
492 if slot_index >= self.slots() {
493 return None;
494 }
495 let offset = (self.index + 1).offset() + slot_index * 8;
496 self.container.get_value(offset)
497 }
498}
499
500impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Link> {
501 pub fn content_index(&self) -> BlockIndex {
503 PayloadFields::content_index(self).into()
504 }
505
506 pub fn link_node_disposition(&self) -> Option<LinkNodeDisposition> {
508 let flag = PayloadFields::disposition_flags(self);
509 LinkNodeDisposition::from_u8(flag)
510 }
511}
512
513impl<T: Deref<Target = Q>, Q: ReadBytes, K: ValueBlockKind> Block<T, K> {
514 pub fn name_index(&self) -> BlockIndex {
516 HeaderFields::value_name_index(self).into()
517 }
518
519 pub fn parent_index(&self) -> BlockIndex {
521 HeaderFields::value_parent_index(self).into()
522 }
523}
524
525impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Node> {
526 pub fn child_count(&self) -> u64 {
528 PayloadFields::value(self)
529 }
530}
531
532impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Tombstone> {
533 pub fn child_count(&self) -> u64 {
535 PayloadFields::value(self)
536 }
537}
538
539impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Free> {
540 pub fn free_next_index(&self) -> BlockIndex {
542 HeaderFields::free_next_index(self).into()
543 }
544}
545
546impl<'a, T: Deref<Target = Q>, Q: ReadBytes + 'a> Block<T, Name> {
547 pub fn length(&self) -> usize {
549 HeaderFields::name_length(self).into()
550 }
551
552 pub fn contents(&'a self) -> Result<&'a str, Error> {
554 let length = self.length();
555 let offset = self.payload_offset();
556 let bytes =
557 self.container.get_slice_at(offset, length).ok_or(Error::InvalidOffset(offset))?;
558 std::str::from_utf8(bytes).map_err(|_| Error::NameNotUtf8)
559 }
560}
561
562impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, K: BlockKind>
563 Block<T, K>
564{
565 pub fn become_free(mut self, next: BlockIndex) -> Block<T, Free> {
567 HeaderFields::set_free_reserved(&mut self, 0);
568 HeaderFields::set_block_type(&mut self, BlockType::Free as u8);
569 HeaderFields::set_free_next_index(&mut self, *next);
570 HeaderFields::set_free_empty(&mut self, 0);
571 Block { index: self.index, container: self.container, _phantom: PhantomData }
572 }
573}
574
575impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, K: BlockKind>
576 Block<T, K>
577{
578 pub fn set_order(&mut self, order: u8) -> Result<(), Error> {
580 if order >= constants::NUM_ORDERS {
581 return Err(Error::InvalidBlockOrder(order));
582 }
583 HeaderFields::set_order(self, order);
584 Ok(())
585 }
586
587 fn write_payload_from_bytes(&mut self, bytes: &[u8]) {
589 let offset = self.payload_offset();
590 self.container.copy_from_slice_at(offset, bytes);
591 }
592}
593
594impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Free> {
595 pub fn free(
597 container: T,
598 index: BlockIndex,
599 order: u8,
600 next_free: BlockIndex,
601 ) -> Result<Block<T, Free>, Error> {
602 if order >= constants::NUM_ORDERS {
603 return Err(Error::InvalidBlockOrder(order));
604 }
605 let mut block = Block::new(container, index);
606 HeaderFields::set_value(&mut block, 0);
607 HeaderFields::set_order(&mut block, order);
608 HeaderFields::set_block_type(&mut block, BlockType::Free as u8);
609 HeaderFields::set_free_next_index(&mut block, *next_free);
610 Ok(block)
611 }
612
613 pub fn become_reserved(mut self) -> Block<T, Reserved> {
615 HeaderFields::set_block_type(&mut self, BlockType::Reserved as u8);
616 HeaderFields::set_reserved_empty(&mut self, 0);
617 Block { index: self.index, container: self.container, _phantom: PhantomData }
618 }
619
620 pub fn set_free_next_index(&mut self, next_free: BlockIndex) {
622 HeaderFields::set_free_next_index(self, *next_free);
623 }
624}
625
626impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Reserved> {
627 pub fn become_header(mut self, size: usize) -> Result<Block<T, Header>, Error> {
629 self.index = BlockIndex::HEADER;
630 HeaderFields::set_order(&mut self, constants::HEADER_ORDER);
631 HeaderFields::set_block_type(&mut self, BlockType::Header as u8);
632 HeaderFields::set_header_magic(&mut self, constants::HEADER_MAGIC_NUMBER);
633 HeaderFields::set_header_version(&mut self, constants::HEADER_VERSION_NUMBER);
634 PayloadFields::set_value(&mut self, 0);
635 let mut this =
636 Block { index: self.index, container: self.container, _phantom: PhantomData };
637 this.set_vmo_size(size.try_into().unwrap())?;
639 Ok(this)
640 }
641
642 pub fn become_extent(mut self, next_extent_index: BlockIndex) -> Block<T, Extent> {
644 HeaderFields::set_block_type(&mut self, BlockType::Extent as u8);
645 HeaderFields::set_extent_next_index(&mut self, *next_extent_index);
646 Block { index: self.index, container: self.container, _phantom: PhantomData }
647 }
648
649 pub fn become_double_value(
651 mut self,
652 value: f64,
653 name_index: BlockIndex,
654 parent_index: BlockIndex,
655 ) -> Block<T, Double> {
656 self.write_value_header(BlockType::DoubleValue, name_index, parent_index);
657 let mut this =
658 Block { index: self.index, container: self.container, _phantom: PhantomData::<Double> };
659 this.set(value);
660 this
661 }
662
663 pub fn become_int_value(
665 mut self,
666 value: i64,
667 name_index: BlockIndex,
668 parent_index: BlockIndex,
669 ) -> Block<T, Int> {
670 self.write_value_header(BlockType::IntValue, name_index, parent_index);
671 let mut this =
672 Block { index: self.index, container: self.container, _phantom: PhantomData::<Int> };
673 this.set(value);
674 this
675 }
676
677 pub fn become_uint_value(
679 mut self,
680 value: u64,
681 name_index: BlockIndex,
682 parent_index: BlockIndex,
683 ) -> Block<T, Uint> {
684 self.write_value_header(BlockType::UintValue, name_index, parent_index);
685 let mut this =
686 Block { index: self.index, container: self.container, _phantom: PhantomData::<Uint> };
687 this.set(value);
688 this
689 }
690
691 pub fn become_bool_value(
693 mut self,
694 value: bool,
695 name_index: BlockIndex,
696 parent_index: BlockIndex,
697 ) -> Block<T, Bool> {
698 self.write_value_header(BlockType::BoolValue, name_index, parent_index);
699 let mut this =
700 Block { index: self.index, container: self.container, _phantom: PhantomData::<Bool> };
701 this.set(value);
702 this
703 }
704
705 pub fn become_node(
707 mut self,
708 name_index: BlockIndex,
709 parent_index: BlockIndex,
710 ) -> Block<T, Node> {
711 self.write_value_header(BlockType::NodeValue, name_index, parent_index);
712 PayloadFields::set_value(&mut self, 0);
713 Block { index: self.index, container: self.container, _phantom: PhantomData }
714 }
715
716 pub fn become_property(
718 mut self,
719 name_index: BlockIndex,
720 parent_index: BlockIndex,
721 format: PropertyFormat,
722 ) -> Block<T, Buffer> {
723 self.write_value_header(BlockType::BufferValue, name_index, parent_index);
724 PayloadFields::set_value(&mut self, 0);
725 PayloadFields::set_property_flags(&mut self, format as u8);
726 Block { index: self.index, container: self.container, _phantom: PhantomData }
727 }
728
729 pub fn become_string_reference(mut self) -> Block<T, StringRef> {
732 HeaderFields::set_block_type(&mut self, BlockType::StringReference as u8);
733 HeaderFields::set_extent_next_index(&mut self, *BlockIndex::EMPTY);
734 HeaderFields::set_string_reference_count(&mut self, 0);
735 Block { index: self.index, container: self.container, _phantom: PhantomData }
736 }
737
738 pub fn become_name(mut self, name: &str) -> Block<T, Name> {
740 let max_len = utils::payload_size_for_order(self.order());
741 let valid_len = name.floor_char_boundary(max_len);
742 let bytes = &name.as_bytes()[..valid_len];
743 HeaderFields::set_block_type(&mut self, BlockType::Name as u8);
744 HeaderFields::set_name_length(&mut self, u16::from_usize(bytes.len()).unwrap());
746 self.write_payload_from_bytes(bytes);
747 Block { index: self.index, container: self.container, _phantom: PhantomData }
748 }
749
750 pub fn become_link(
752 mut self,
753 name_index: BlockIndex,
754 parent_index: BlockIndex,
755 content_index: BlockIndex,
756 disposition_flags: LinkNodeDisposition,
757 ) -> Block<T, Link> {
758 self.write_value_header(BlockType::LinkValue, name_index, parent_index);
759 PayloadFields::set_value(&mut self, 0);
760 PayloadFields::set_content_index(&mut self, *content_index);
761 PayloadFields::set_disposition_flags(&mut self, disposition_flags as u8);
762 Block { index: self.index, container: self.container, _phantom: PhantomData }
763 }
764
765 pub fn become_array_value<S: ArraySlotKind>(
767 mut self,
768 slots: usize,
769 format: ArrayFormat,
770 name_index: BlockIndex,
771 parent_index: BlockIndex,
772 ) -> Result<Block<T, Array<S>>, Error> {
773 if S::block_type() == BlockType::StringReference && format != ArrayFormat::Default {
774 return Err(Error::InvalidArrayType(self.index));
775 }
776 let order = self.order();
777 let max_capacity = max_array_capacity::<S>(order);
778
779 if slots > max_capacity {
780 return Err(Error::array_capacity_exceeded(slots, order, max_capacity));
781 }
782 self.write_value_header(BlockType::ArrayValue, name_index, parent_index);
783 PayloadFields::set_value(&mut self, 0);
784 PayloadFields::set_array_entry_type(&mut self, S::block_type() as u8);
785 PayloadFields::set_array_flags(&mut self, format as u8);
786 PayloadFields::set_array_slots_count(&mut self, slots as u8);
787 let mut this =
788 Block { index: self.index, container: self.container, _phantom: PhantomData };
789 this.clear(0);
790 Ok(this)
791 }
792
793 #[cfg_attr(debug_assertions, track_caller)]
795 fn write_value_header(
796 &mut self,
797 block_type: BlockType,
798 name_index: BlockIndex,
799 parent_index: BlockIndex,
800 ) {
801 debug_assert!(block_type.is_any_value(), "Unexpected block: {block_type}");
802 HeaderFields::set_block_type(self, block_type as u8);
803 HeaderFields::set_value_name_index(self, *name_index);
804 HeaderFields::set_value_parent_index(self, *parent_index);
805 }
806}
807
808impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Header> {
809 #[doc(hidden)]
812 pub fn set_magic(&mut self, value: u32) {
813 HeaderFields::set_header_magic(self, value);
814 }
815
816 pub fn set_vmo_size(&mut self, size: u32) -> Result<(), Error> {
819 if self.order() != constants::HEADER_ORDER {
820 return Ok(());
821 }
822 self.container.set_value((self.index + 1).offset(), size)
823 }
824
825 pub fn freeze(&mut self) -> u64 {
827 let value = PayloadFields::value(self);
828 PayloadFields::set_value(self, constants::VMO_FROZEN);
829 value
830 }
831
832 pub fn thaw(&mut self, generation: u64) {
834 PayloadFields::set_value(self, generation)
835 }
836
837 pub fn lock(&mut self) {
839 self.check_locked(false);
840 self.increment_generation_count();
841 fence(Ordering::Acquire);
842 }
843
844 pub fn unlock(&mut self) {
846 self.check_locked(true);
847 fence(Ordering::Release);
848 self.increment_generation_count();
849 }
850
851 fn increment_generation_count(&mut self) {
853 let value = PayloadFields::value(self);
854 let new_value = value.wrapping_add(1);
856 PayloadFields::set_value(self, new_value);
857 }
858}
859
860impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Node> {
861 pub fn become_tombstone(mut self) -> Block<T, Tombstone> {
863 HeaderFields::set_block_type(&mut self, BlockType::Tombstone as u8);
864 HeaderFields::set_tombstone_empty(&mut self, 0);
865 Block { index: self.index, container: self.container, _phantom: PhantomData }
866 }
867
868 pub fn set_child_count(&mut self, count: u64) {
870 PayloadFields::set_value(self, count);
871 }
872}
873
874impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, S: ArraySlotKind>
875 Block<T, Array<S>>
876{
877 pub fn clear(&mut self, start_slot_index: usize) {
879 let array_slots = self.slots() - start_slot_index;
880 let type_size = self.entry_type_size().unwrap();
884 let offset = (self.index + 1).offset() + start_slot_index * type_size;
885 if let Some(slice) = self.container.get_slice_mut_at(offset, array_slots * type_size) {
886 slice.fill(0);
887 }
888 }
889}
890
891impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes>
892 Block<T, Array<StringRef>>
893{
894 pub fn set_string_slot(&mut self, slot_index: usize, string_index: BlockIndex) {
896 if slot_index >= self.slots() {
897 return;
898 }
899 let type_size = StringRef::array_entry_type_size();
901 let _ = self
902 .container
903 .set_value((self.index + 1).offset() + slot_index * type_size, *string_index);
904 }
905}
906
907impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Array<Int>> {
908 pub fn set(&mut self, slot_index: usize, value: i64) {
910 if slot_index >= self.slots() {
911 return;
912 }
913 let type_size = Int::array_entry_type_size();
914 let _ = self.container.set_value((self.index + 1).offset() + slot_index * type_size, value);
915 }
916}
917
918impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes>
919 Block<T, Array<Double>>
920{
921 pub fn set(&mut self, slot_index: usize, value: f64) {
923 if slot_index >= self.slots() {
924 return;
925 }
926 let type_size = Double::array_entry_type_size();
927 let _ = self.container.set_value((self.index + 1).offset() + slot_index * type_size, value);
928 }
929}
930
931impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Array<Uint>> {
932 pub fn set(&mut self, slot_index: usize, value: u64) {
934 if slot_index >= self.slots() {
935 return;
936 }
937 let type_size = Uint::array_entry_type_size();
938 let _ = self.container.set_value((self.index + 1).offset() + slot_index * type_size, value);
939 }
940}
941
942impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Extent> {
943 pub fn set_next_index(&mut self, next_extent_index: BlockIndex) {
945 HeaderFields::set_extent_next_index(self, *next_extent_index);
946 }
947
948 pub fn set_contents(&mut self, value: &[u8]) -> usize {
950 let order = self.order();
951 let max_bytes = utils::payload_size_for_order(order);
952 let mut bytes = value;
953 if bytes.len() > max_bytes {
954 bytes = &bytes[..min(bytes.len(), max_bytes)];
955 }
956 self.write_payload_from_bytes(bytes);
957 bytes.len()
958 }
959}
960
961impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, StringRef> {
962 pub fn set_next_index(&mut self, next_extent_index: BlockIndex) {
964 HeaderFields::set_extent_next_index(self, *next_extent_index);
965 }
966
967 pub fn set_total_length(&mut self, length: u32) {
969 PayloadFields::set_property_total_length(self, length);
970 }
971
972 pub fn increment_ref_count(&mut self) -> Result<(), Error> {
974 let cur = HeaderFields::string_reference_count(self);
975 if cur < constants::MAX_REFERENCE_COUNT {
976 HeaderFields::set_string_reference_count(self, cur + 1);
977 }
978 Ok(())
979 }
980
981 pub fn decrement_ref_count(&mut self) -> Result<(), Error> {
983 let cur = HeaderFields::string_reference_count(self);
984 if cur < constants::MAX_REFERENCE_COUNT {
985 let new_count = cur.checked_sub(1).ok_or(Error::InvalidReferenceCount)?;
986 HeaderFields::set_string_reference_count(self, new_count);
987 }
988 Ok(())
989 }
990
991 pub fn write_inline(&mut self, value: &[u8]) -> usize {
995 let payload_offset = self.payload_offset();
996 self.set_total_length(value.len() as u32);
997 let max_len = utils::payload_size_for_order(self.order())
998 - constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES;
999 let bytes = min(value.len(), max_len);
1002 let to_inline = &value[..bytes];
1003 self.container.copy_from_slice_at(
1004 payload_offset + constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES,
1005 to_inline,
1006 );
1007 bytes
1008 }
1009}
1010
1011impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Double> {
1012 pub fn set(&mut self, value: f64) {
1014 PayloadFields::set_value(self, value.to_bits());
1015 }
1016}
1017
1018impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Int> {
1019 pub fn set(&mut self, value: i64) {
1021 PayloadFields::set_value(self, LittleEndian::read_u64(&value.to_le_bytes()));
1022 }
1023}
1024
1025impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Uint> {
1026 pub fn set(&mut self, value: u64) {
1028 PayloadFields::set_value(self, value);
1029 }
1030}
1031
1032impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Bool> {
1033 pub fn set(&mut self, value: bool) {
1035 PayloadFields::set_value(self, value as u64);
1036 }
1037}
1038
1039impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Buffer> {
1040 pub fn set_total_length(&mut self, length: u32) {
1042 PayloadFields::set_property_total_length(self, length);
1043 }
1044
1045 pub fn set_extent_index(&mut self, index: BlockIndex) {
1047 PayloadFields::set_property_extent_index(self, *index);
1050 }
1051}
1052
1053impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Tombstone> {
1054 pub fn set_child_count(&mut self, count: u64) {
1056 PayloadFields::set_value(self, count);
1057 }
1058}
1059
1060impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, K: ValueBlockKind>
1061 Block<T, K>
1062{
1063 pub fn set_parent(&mut self, new_parent_index: BlockIndex) {
1064 HeaderFields::set_value_parent_index(self, *new_parent_index);
1065 }
1066
1067 pub fn set_name(&mut self, new_name_index: BlockIndex) {
1068 HeaderFields::set_value_name_index(self, *new_name_index);
1069 }
1070}
1071
1072fn max_array_capacity<S: ArraySlotKind>(order: u8) -> usize {
1074 array_capacity(S::array_entry_type_size(), order)
1075}
1076
1077fn array_capacity(slot_size: usize, order: u8) -> usize {
1078 (utils::order_to_size(order)
1079 - constants::HEADER_SIZE_BYTES
1080 - constants::ARRAY_PAYLOAD_METADATA_SIZE_BYTES)
1081 / slot_size
1082}
1083
1084pub mod testing {
1085 use super::*;
1086
1087 pub fn override_header<T: WriteBytes + ReadBytes, K: BlockKind>(
1088 block: &mut Block<&mut T, K>,
1089 value: u64,
1090 ) {
1091 let _ = block.container.set_value(block.header_offset(), value);
1092 }
1093
1094 pub fn override_payload<T: WriteBytes + ReadBytes, K: BlockKind>(
1095 block: &mut Block<&mut T, K>,
1096 value: u64,
1097 ) {
1098 let _ = block.container.set_value(block.payload_offset(), value);
1099 }
1100}
1101
1102#[cfg(test)]
1103mod tests {
1104 use super::*;
1105 use crate::{Container, CopyBytes};
1106
1107 macro_rules! assert_8_bytes {
1108 ($container:ident, $offset:expr, $expected:expr) => {
1109 let slice = $container.get_slice_at($offset, 8).unwrap();
1110 assert_eq!(slice, &$expected);
1111 };
1112 }
1113
1114 #[fuchsia::test]
1115 fn test_new_free() {
1116 let (mut container, _storage) =
1117 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1118 assert!(Block::free(&mut container, 3.into(), constants::NUM_ORDERS, 1.into()).is_err());
1119
1120 let res = Block::free(&mut container, BlockIndex::EMPTY, 3, 1.into());
1121 assert!(res.is_ok());
1122 let block = res.unwrap();
1123 assert_eq!(*block.index(), 0);
1124 assert_eq!(block.order(), 3);
1125 assert_eq!(*block.free_next_index(), 1);
1126 assert_eq!(block.block_type(), Some(BlockType::Free));
1127 assert_8_bytes!(container, 0, [0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]);
1128 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1129 }
1130
1131 #[fuchsia::test]
1132 fn test_set_order() {
1133 let (mut container, _storage) =
1134 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1135 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1136 assert!(block.set_order(3).is_ok());
1137 assert_eq!(block.order(), 3);
1138 }
1139
1140 #[fuchsia::test]
1141 fn test_become_reserved() {
1142 let (mut container, _storage) =
1143 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1144 let block = Block::free(&mut container, BlockIndex::EMPTY, 1, 2.into()).unwrap();
1145 let block = block.become_reserved();
1146 assert_eq!(block.block_type(), Some(BlockType::Reserved));
1147 assert_8_bytes!(container, 0, [0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1148 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1149 }
1150
1151 #[fuchsia::test]
1152 fn test_become_string_reference() {
1153 let (mut container, _storage) =
1154 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1155 let block = get_reserved(&mut container).become_string_reference();
1156 assert_eq!(block.block_type(), Some(BlockType::StringReference));
1157 assert_eq!(*block.next_extent(), 0);
1158 assert_eq!(block.reference_count(), 0);
1159 assert_eq!(block.total_length(), 0);
1160 assert_eq!(block.inline_data().unwrap(), Vec::<u8>::new());
1161 assert_8_bytes!(container, 0, [0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1162 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1163 }
1164
1165 #[fuchsia::test]
1166 fn test_inline_string_reference() {
1167 let (mut container, _storage) =
1168 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1169 let mut block = get_reserved(&mut container);
1170 block.set_order(0).unwrap();
1171 let mut block = block.become_string_reference();
1172
1173 assert_eq!(block.write_inline("ab".as_bytes()), 2);
1174 assert_eq!(block.reference_count(), 0);
1175 assert_eq!(block.total_length(), 2);
1176 assert_eq!(block.order(), 0);
1177 assert_eq!(*block.next_extent(), 0);
1178 assert_eq!(block.inline_data().unwrap(), "ab".as_bytes());
1179
1180 assert_eq!(block.write_inline("abcd".as_bytes()), 4);
1181 assert_eq!(block.reference_count(), 0);
1182 assert_eq!(block.total_length(), 4);
1183 assert_eq!(block.order(), 0);
1184 assert_eq!(*block.next_extent(), 0);
1185 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1186
1187 assert_eq!(
1188 block.write_inline("abcdefghijklmnopqrstuvwxyz".as_bytes()),
1189 4 );
1191 assert_eq!(block.reference_count(), 0);
1192 assert_eq!(block.total_length(), 26);
1193 assert_eq!(block.order(), 0);
1194 assert_eq!(*block.next_extent(), 0);
1195 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1196
1197 assert_eq!(block.write_inline("abcdef".as_bytes()), 4);
1198 assert_eq!(block.reference_count(), 0);
1199 assert_eq!(block.total_length(), 6);
1200 assert_eq!(block.order(), 0);
1201 assert_eq!(*block.next_extent(), 0);
1202 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1203 }
1204
1205 #[fuchsia::test]
1206 fn test_string_reference_count() {
1207 let (mut container, _storage) =
1208 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1209 let mut block = get_reserved(&mut container);
1210 block.set_order(0).unwrap();
1211 let mut block = block.become_string_reference();
1212 assert_eq!(block.reference_count(), 0);
1213
1214 assert!(block.increment_ref_count().is_ok());
1215 assert_eq!(block.reference_count(), 1);
1216
1217 assert!(block.decrement_ref_count().is_ok());
1218 assert_eq!(block.reference_count(), 0);
1219
1220 assert!(block.decrement_ref_count().is_err());
1221 assert_eq!(block.reference_count(), 0);
1222
1223 HeaderFields::set_string_reference_count(&mut block, constants::MAX_REFERENCE_COUNT);
1224 assert_eq!(block.reference_count(), constants::MAX_REFERENCE_COUNT);
1225
1226 assert!(block.increment_ref_count().is_ok());
1227 assert_eq!(block.reference_count(), constants::MAX_REFERENCE_COUNT);
1228
1229 assert!(block.decrement_ref_count().is_ok());
1230 assert_eq!(block.reference_count(), constants::MAX_REFERENCE_COUNT);
1231 }
1232
1233 #[fuchsia::test]
1234 fn test_become_header() {
1235 let (mut container, _storage) =
1236 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1237 let block =
1238 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1239 assert_eq!(block.block_type(), Some(BlockType::Header));
1240 assert_eq!(*block.index(), 0);
1241 assert_eq!(block.order(), constants::HEADER_ORDER);
1242 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1243 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1244 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::MIN_ORDER_SIZE * 2);
1245 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1246 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1247 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1248 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1249 }
1250
1251 #[fuchsia::test]
1252 fn test_header_without_size() {
1253 let (mut container, _storage) =
1254 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1255 let block =
1256 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1257 assert_eq!(block.order(), constants::HEADER_ORDER);
1258 assert!(block.vmo_size().unwrap().is_some());
1259
1260 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1261
1262 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1264 assert!(block.set_order(0).is_ok());
1265 assert_eq!(block.vmo_size().unwrap(), None);
1266 assert!(block.set_vmo_size(123456789).is_ok());
1268 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1269 }
1270
1271 #[fuchsia::test]
1272 fn test_freeze_thaw_header() {
1273 let (mut container, _storage) =
1274 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1275 let block =
1276 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1277 assert_eq!(block.block_type(), Some(BlockType::Header));
1278 assert_eq!(*block.index(), 0);
1279 assert_eq!(block.order(), constants::HEADER_ORDER);
1280 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1281 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1282 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1283 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1284 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1285 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1286
1287 let old = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).freeze();
1288 assert_8_bytes!(container, 8, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1289 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1290 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1291 container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).thaw(old);
1292 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1293 assert_8_bytes!(container, 16, [0x020, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1294 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1295 }
1296
1297 #[fuchsia::test]
1298 fn test_unaligned_buffer_access() {
1299 #[repr(C, packed)]
1300 struct Unaligned(u8, [u8; 32]);
1301
1302 let (mut container, _storage) =
1303 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1304 let _ = get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1305
1306 let mut unaligned = Unaligned(0, [0; 32]);
1307 assert_eq!(unaligned.0, 0);
1308 unaligned.1.copy_from_slice(container.get_slice_at(0, 32).unwrap());
1309
1310 let block = unaligned.1.block_at_unchecked::<Header>(BlockIndex::EMPTY);
1311 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1312 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1313 assert_eq!(block.generation_count(), 0);
1314 }
1315
1316 #[fuchsia::test]
1317 fn test_set_value_invalid_offset() {
1318 let mut buffer = [0u8; 16];
1319 assert_eq!(buffer.set_value(16, 42u32), Err(Error::InvalidOffset(16)));
1320 assert_eq!(buffer.set_value(14, 42u32), Err(Error::InvalidOffset(14)));
1321 assert_eq!(buffer.set_value(0, 42u32), Ok(()));
1322 assert_eq!(buffer.get_value::<u32>(0), Some(42));
1323 }
1324
1325 #[fuchsia::test]
1326 #[should_panic]
1327 fn test_cant_unlock_locked_header() {
1328 let (mut container, _storage) =
1329 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1330 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1331 block.unlock();
1333 }
1334
1335 #[fuchsia::test]
1336 #[should_panic]
1337 fn test_cant_lock_locked_header() {
1338 let (mut container, _storage) =
1339 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1340 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1341 block.lock();
1342 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1344 block.lock();
1345 }
1346
1347 #[fuchsia::test]
1348 #[should_panic]
1349 fn test_header_overflow() {
1350 let (mut container, _storage) =
1353 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1354 container.set_value(8, u64::MAX).unwrap();
1355 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1356 block.lock();
1357 }
1358
1359 #[fuchsia::test]
1360 fn test_lock_unlock_header() {
1361 let (mut container, _storage) =
1362 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1363 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1364 block.lock();
1365 assert!(block.is_locked());
1366 assert_eq!(block.generation_count(), 1);
1367 let header_bytes: [u8; 8] = [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50];
1368 assert_8_bytes!(container, 0, header_bytes[..]);
1369 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1370 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1371 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1372 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1373 block.unlock();
1374 assert!(!block.is_locked());
1375 assert_eq!(block.generation_count(), 2);
1376 assert_8_bytes!(container, 0, header_bytes[..]);
1377 assert_8_bytes!(container, 8, [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1378 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1379 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1380
1381 container.set_value(8, u64::MAX).unwrap();
1383 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1384 block.unlock();
1385 assert_eq!(block.generation_count(), 0);
1386 assert_8_bytes!(container, 0, header_bytes[..]);
1387 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1388 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1389 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1390 }
1391
1392 #[fuchsia::test]
1393 fn test_header_vmo_size() {
1394 let (mut container, _storage) =
1395 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1396 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1397 assert!(block.set_vmo_size(constants::DEFAULT_VMO_SIZE_BYTES.try_into().unwrap()).is_ok());
1398 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1399 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1400 assert_8_bytes!(container, 16, [0x00, 0x00, 0x4, 0x00, 0x00, 0x00, 0x00, 0x00]);
1401 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1402 let block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1403 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::DEFAULT_VMO_SIZE_BYTES);
1404 }
1405
1406 #[fuchsia::test]
1407 fn test_become_tombstone() {
1408 let (mut container, _storage) =
1409 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1410 let mut block = get_reserved(&mut container).become_node(2.into(), 3.into());
1411 block.set_child_count(4);
1412 let block = block.become_tombstone();
1413 assert_eq!(block.block_type(), Some(BlockType::Tombstone));
1414 assert_eq!(block.child_count(), 4);
1415 assert_8_bytes!(container, 0, [0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1416 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1417 }
1418
1419 #[fuchsia::test]
1420 fn test_child_count() {
1421 let (mut container, _storage) =
1422 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1423 let _ = get_reserved(&mut container).become_node(2.into(), 3.into());
1424 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1425 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1426 let mut block = container.block_at_unchecked_mut::<Node>(BlockIndex::EMPTY);
1427 block.set_child_count(4);
1428 assert_eq!(block.child_count(), 4);
1429 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1430 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1431 }
1432
1433 #[fuchsia::test]
1434 fn test_free() {
1435 let (mut container, _storage) =
1436 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1437 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1438 block.set_free_next_index(3.into());
1439 assert_eq!(*block.free_next_index(), 3);
1440 assert_8_bytes!(container, 0, [0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1441 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1442 }
1443
1444 #[fuchsia::test]
1445 fn test_extent() {
1446 let (mut container, _storage) =
1447 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1448 let block = get_reserved(&mut container).become_extent(3.into());
1449 assert_eq!(block.block_type(), Some(BlockType::Extent));
1450 assert_eq!(*block.next_extent(), 3);
1451 assert_8_bytes!(container, 0, [0x01, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1452 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1453
1454 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1455 assert_eq!(block.set_contents("test-rust-inspect".as_bytes()), 17);
1456 assert_eq!(
1457 String::from_utf8(block.contents().unwrap().to_vec()).unwrap(),
1458 "test-rust-inspect\0\0\0\0\0\0\0"
1459 );
1460 let slice = container.get_slice_at(8, 17).unwrap();
1461 assert_eq!(slice, "test-rust-inspect".as_bytes());
1462 let slice = container.get_slice_at(25, 7).unwrap();
1463 assert_eq!(slice, &[0, 0, 0, 0, 0, 0, 0]);
1464
1465 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1466 block.set_next_index(4.into());
1467 assert_eq!(*block.next_extent(), 4);
1468 }
1469
1470 #[fuchsia::test]
1471 fn test_double_value() {
1472 let (mut container, _storage) =
1473 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1474 let block = get_reserved(&mut container).become_double_value(1.0, 2.into(), 3.into());
1475 assert_eq!(block.block_type(), Some(BlockType::DoubleValue));
1476 assert_eq!(*block.name_index(), 2);
1477 assert_eq!(*block.parent_index(), 3);
1478 assert_eq!(block.value(), 1.0);
1479 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1480 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f]);
1481
1482 let mut block = container.block_at_unchecked_mut::<Double>(BlockIndex::EMPTY);
1483 block.set(5.0);
1484 assert_eq!(block.value(), 5.0);
1485 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1486 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40]);
1487 }
1488
1489 #[fuchsia::test]
1490 fn test_int_value() {
1491 let (mut container, _storage) =
1492 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1493 let block = get_reserved(&mut container).become_int_value(1, 2.into(), 3.into());
1494 assert_eq!(block.block_type(), Some(BlockType::IntValue));
1495 assert_eq!(*block.name_index(), 2);
1496 assert_eq!(*block.parent_index(), 3);
1497 assert_eq!(block.value(), 1);
1498 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1499 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1500
1501 let mut block = container.block_at_unchecked_mut::<Int>(BlockIndex::EMPTY);
1502 block.set(-5);
1503 assert_eq!(block.value(), -5);
1504 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1505 assert_8_bytes!(container, 8, [0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
1506 }
1507
1508 #[fuchsia::test]
1509 fn test_uint_value() {
1510 let (mut container, _storage) =
1511 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1512 let block = get_reserved(&mut container).become_uint_value(1, 2.into(), 3.into());
1513 assert_eq!(block.block_type(), Some(BlockType::UintValue));
1514 assert_eq!(*block.name_index(), 2);
1515 assert_eq!(*block.parent_index(), 3);
1516 assert_eq!(block.value(), 1);
1517 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1518 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1519
1520 let mut block = container.block_at_unchecked_mut::<Uint>(BlockIndex::EMPTY);
1521 block.set(5);
1522 assert_eq!(block.value(), 5);
1523 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1524 assert_8_bytes!(container, 8, [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1525 }
1526
1527 #[fuchsia::test]
1528 fn test_bool_value() {
1529 let (mut container, _storage) =
1530 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1531 let block = get_reserved(&mut container).become_bool_value(false, 2.into(), 3.into());
1532 assert_eq!(block.block_type(), Some(BlockType::BoolValue));
1533 assert_eq!(*block.name_index(), 2);
1534 assert_eq!(*block.parent_index(), 3);
1535 assert!(!block.value());
1536 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1537 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1538
1539 let mut block = container.block_at_unchecked_mut::<Bool>(BlockIndex::EMPTY);
1540 block.set(true);
1541 assert!(block.value());
1542 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1543 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1544 }
1545
1546 #[fuchsia::test]
1547 fn test_become_node() {
1548 let (mut container, _storage) =
1549 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1550 let block = get_reserved(&mut container).become_node(2.into(), 3.into());
1551 assert_eq!(block.block_type(), Some(BlockType::NodeValue));
1552 assert_eq!(*block.name_index(), 2);
1553 assert_eq!(*block.parent_index(), 3);
1554 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1555 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1556 }
1557
1558 #[fuchsia::test]
1559 fn test_property() {
1560 let (mut container, _storage) =
1561 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1562 let block =
1563 get_reserved(&mut container).become_property(2.into(), 3.into(), PropertyFormat::Bytes);
1564 assert_eq!(block.block_type(), Some(BlockType::BufferValue));
1565 assert_eq!(*block.name_index(), 2);
1566 assert_eq!(*block.parent_index(), 3);
1567 assert_eq!(block.format(), Some(PropertyFormat::Bytes));
1568 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1569 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1570
1571 let (mut bad_container, _storage) =
1572 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1573 let mut bad_format_bytes = [0u8; constants::MIN_ORDER_SIZE];
1574 bad_format_bytes[15] = 0x30;
1575 bad_container.copy_from_slice(&bad_format_bytes);
1576 let bad_block = Block::<_, Buffer>::new(&bad_container, BlockIndex::EMPTY);
1577 assert_eq!(bad_block.format(), None);
1578
1579 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1580 block.set_extent_index(4.into());
1581 assert_eq!(*block.extent_index(), 4);
1582 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1583 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1584
1585 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1586 block.set_total_length(10);
1587 assert_eq!(block.total_length(), 10);
1588 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1589 assert_8_bytes!(container, 8, [0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1590 }
1591
1592 #[fuchsia::test]
1593 fn test_name() {
1594 let (mut container, _storage) =
1595 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1596 let block = get_reserved(&mut container).become_name("test-rust-inspect");
1597 assert_eq!(block.block_type(), Some(BlockType::Name));
1598 assert_eq!(block.length(), 17);
1599 assert_eq!(block.contents().unwrap(), "test-rust-inspect");
1600 assert_8_bytes!(container, 0, [0x01, 0x09, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
1601 let slice = container.get_slice_at(8, 17).unwrap();
1602 assert_eq!(slice, "test-rust-inspect".as_bytes());
1603 let slice = container.get_slice_at(25, 7).unwrap();
1604 assert_eq!(slice, [0, 0, 0, 0, 0, 0, 0]);
1605
1606 container.set_value::<u8>(24, 0xff).unwrap();
1607 let bad_block = Block::<_, Name>::new(&container, BlockIndex::EMPTY);
1608 assert_eq!(bad_block.length(), 17); assert!(bad_block.contents().is_err()); let (mut container, _storage) =
1614 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1615 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstuvwxyz");
1616 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstuvwx");
1617
1618 let (mut container, _storage) =
1619 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1620 let block = get_reserved(&mut container).become_name("😀abcdefghijklmnopqrstuvwxyz");
1621 assert_eq!(block.contents().unwrap(), "😀abcdefghijklmnopqrst");
1622
1623 let (mut container, _storage) =
1624 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1625 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstu😀");
1626 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstu");
1627 let byte = container.get_value::<u8>(31).unwrap();
1628 assert_eq!(byte, 0);
1629
1630 let (mut container, _storage) =
1631 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1632 let block = get_reserved(&mut container).become_name("🦀🦀🦀🦀🦀🦀🦀🦀");
1633 assert_eq!(block.contents().unwrap(), "🦀🦀🦀🦀🦀🦀");
1634 }
1635
1636 #[fuchsia::test]
1637 fn test_invalid_type_for_array() {
1638 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1639 container.get_slice_mut_at(24, 2048 - 24).unwrap().fill(14);
1640
1641 fn become_array<S: ArraySlotKind>(
1642 container: &mut Container,
1643 format: ArrayFormat,
1644 ) -> Result<Block<&mut Container, Array<S>>, Error> {
1645 get_reserved_of_order(container, 4).become_array_value::<S>(
1646 4,
1647 format,
1648 BlockIndex::EMPTY,
1649 BlockIndex::EMPTY,
1650 )
1651 }
1652
1653 assert!(become_array::<Int>(&mut container, ArrayFormat::Default).is_ok());
1654 assert!(become_array::<Uint>(&mut container, ArrayFormat::Default).is_ok());
1655 assert!(become_array::<Double>(&mut container, ArrayFormat::Default).is_ok());
1656 assert!(become_array::<StringRef>(&mut container, ArrayFormat::Default).is_ok());
1657
1658 for format in [ArrayFormat::LinearHistogram, ArrayFormat::ExponentialHistogram] {
1659 assert!(become_array::<Int>(&mut container, format).is_ok());
1660 assert!(become_array::<Uint>(&mut container, format).is_ok());
1661 assert!(become_array::<Double>(&mut container, format).is_ok());
1662 assert!(become_array::<StringRef>(&mut container, format).is_err());
1663 }
1664 }
1665
1666 #[fuchsia::test]
1672 fn test_string_arrays() {
1673 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1674 container.get_slice_mut_at(48, 2048 - 48).unwrap().fill(14);
1675
1676 let parent_index = BlockIndex::new(0);
1677 let name_index = BlockIndex::new(1);
1678 let mut block = get_reserved(&mut container)
1679 .become_array_value::<StringRef>(4, ArrayFormat::Default, name_index, parent_index)
1680 .unwrap();
1681
1682 for i in 0..4 {
1683 block.set_string_slot(i, ((i + 4) as u32).into());
1684 }
1685
1686 for i in 0..4 {
1687 let read_index = block.get_string_index_at(i).unwrap();
1688 assert_eq!(*read_index, (i + 4) as u32);
1689 }
1690
1691 assert_8_bytes!(
1692 container,
1693 0,
1694 [
1695 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
1698 ]
1699 );
1700 assert_8_bytes!(container, 8, [0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1701 for i in 0..4 {
1702 let slice = container.get_slice_at(16 + (i * 4), 4).unwrap();
1703 assert_eq!(slice, [(i as u8 + 4), 0x00, 0x00, 0x00]);
1704 }
1705 }
1706
1707 #[fuchsia::test]
1708 fn become_array() {
1709 let (mut container, _storage) = Container::read_and_write(128).unwrap();
1711 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1712
1713 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1714 .unwrap()
1715 .become_reserved()
1716 .become_array_value::<Int>(
1717 14,
1718 ArrayFormat::Default,
1719 BlockIndex::EMPTY,
1720 BlockIndex::EMPTY,
1721 )
1722 .unwrap();
1723 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1724 slice
1725 .iter()
1726 .enumerate()
1727 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1728
1729 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1730 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1731 .unwrap()
1732 .become_reserved()
1733 .become_array_value::<Int>(
1734 14,
1735 ArrayFormat::LinearHistogram,
1736 BlockIndex::EMPTY,
1737 BlockIndex::EMPTY,
1738 )
1739 .unwrap();
1740 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1741 slice
1742 .iter()
1743 .enumerate()
1744 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1745
1746 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1747 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1748 .unwrap()
1749 .become_reserved()
1750 .become_array_value::<Int>(
1751 14,
1752 ArrayFormat::ExponentialHistogram,
1753 BlockIndex::EMPTY,
1754 BlockIndex::EMPTY,
1755 )
1756 .unwrap();
1757 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1758 slice
1759 .iter()
1760 .enumerate()
1761 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1762
1763 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1764 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1765 .unwrap()
1766 .become_reserved()
1767 .become_array_value::<StringRef>(
1768 28,
1769 ArrayFormat::Default,
1770 BlockIndex::EMPTY,
1771 BlockIndex::EMPTY,
1772 )
1773 .unwrap();
1774 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1775 slice
1776 .iter()
1777 .enumerate()
1778 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1779 }
1780
1781 #[fuchsia::test]
1782 fn uint_array_value() {
1783 let (mut container, _storage) =
1784 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1785 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1786 .unwrap()
1787 .become_reserved()
1788 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1789 .unwrap();
1790
1791 assert_eq!(block.block_type(), Some(BlockType::ArrayValue));
1792 assert_eq!(*block.parent_index(), 2);
1793 assert_eq!(*block.name_index(), 3);
1794 assert_eq!(block.format(), Some(ArrayFormat::LinearHistogram));
1795 assert_eq!(block.slots(), 4);
1796 assert_eq!(block.entry_type(), Some(BlockType::UintValue));
1797
1798 for i in 0..4 {
1799 block.set(i, (i as u64 + 1) * 5);
1800 }
1801 block.set(4, 3);
1802 block.set(7, 5);
1803
1804 assert_8_bytes!(container, 0, [0x02, 0x0b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00]);
1805 assert_8_bytes!(container, 8, [0x15, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1806 for i in 0..4 {
1807 assert_8_bytes!(
1808 container,
1809 8 * (i + 2),
1810 [(i as u8 + 1) * 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1811 );
1812 }
1813
1814 let (mut bad_container, _storage) =
1815 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1816 let mut bad_bytes = [0u8; constants::MIN_ORDER_SIZE];
1817 container.copy_bytes(&mut bad_bytes[..]);
1818 bad_bytes[8] = 0x12; bad_container.copy_from_slice(&bad_bytes);
1820 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1821 assert_eq!(bad_block.format(), Some(ArrayFormat::LinearHistogram));
1822 assert_eq!(bad_block.entry_type(), None);
1824
1825 bad_bytes[8] = 0xef; bad_container.copy_from_slice(&bad_bytes);
1827 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1828 assert_eq!(bad_block.format(), None);
1829 assert_eq!(bad_block.entry_type(), None);
1830
1831 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1832 for i in 0..4 {
1833 assert_eq!(block.get(i), Some((i as u64 + 1) * 5));
1834 }
1835 assert_eq!(block.get(4), None);
1836 }
1837
1838 #[fuchsia::test]
1839 fn array_slots_bigger_than_block_order() {
1840 let (mut container, _storage) =
1841 Container::read_and_write(constants::MAX_ORDER_SIZE).unwrap();
1842 assert!(
1845 Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1846 .unwrap()
1847 .become_reserved()
1848 .become_array_value::<Int>(257, ArrayFormat::Default, 1.into(), 2.into())
1849 .is_err()
1850 );
1851 assert!(
1852 Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1853 .unwrap()
1854 .become_reserved()
1855 .become_array_value::<Int>(254, ArrayFormat::Default, 1.into(), 2.into())
1856 .is_ok()
1857 );
1858
1859 assert!(
1862 Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1863 .unwrap()
1864 .become_reserved()
1865 .become_array_value::<Int>(8, ArrayFormat::Default, 1.into(), 2.into())
1866 .is_err()
1867 );
1868 assert!(
1869 Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1870 .unwrap()
1871 .become_reserved()
1872 .become_array_value::<Int>(6, ArrayFormat::Default, 1.into(), 2.into())
1873 .is_ok()
1874 );
1875 }
1876
1877 #[fuchsia::test]
1878 fn array_clear() {
1879 let (mut container, _storage) =
1880 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1881
1882 let sample = [0xff, 0xff, 0xff];
1884 container.copy_from_slice_at(48, &sample);
1885
1886 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1887 .unwrap()
1888 .become_reserved()
1889 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1890 .unwrap();
1891
1892 for i in 0..4 {
1893 block.set(i, (i + 1) as u64);
1894 }
1895
1896 block.clear(1);
1897
1898 assert_eq!(1, block.get(0).expect("get uint 0"));
1899 assert_8_bytes!(container, 16, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1900
1901 for i in 1..4 {
1902 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1903 assert_eq!(0, block.get(i).expect("get uint"));
1904 assert_8_bytes!(
1905 container,
1906 16 + (i * 8),
1907 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1908 );
1909 }
1910
1911 let slice = container.get_slice_at(48, 3).unwrap();
1913 assert_eq!(slice, &sample[..]);
1914 }
1915
1916 #[fuchsia::test]
1917 fn become_link() {
1918 let (mut container, _storage) =
1919 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1920 let block = get_reserved(&mut container).become_link(
1921 BlockIndex::new(1),
1922 BlockIndex::new(2),
1923 BlockIndex::new(3),
1924 LinkNodeDisposition::Inline,
1925 );
1926 assert_eq!(*block.name_index(), 1);
1927 assert_eq!(*block.parent_index(), 2);
1928 assert_eq!(*block.content_index(), 3);
1929 assert_eq!(block.block_type(), Some(BlockType::LinkValue));
1930 assert_eq!(block.link_node_disposition(), Some(LinkNodeDisposition::Inline));
1931 assert_8_bytes!(container, 0, [0x01, 0x0c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00]);
1932 assert_8_bytes!(container, 8, [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1933 }
1934
1935 #[test]
1936 fn array_capacity_numeric() {
1937 assert_eq!(2, max_array_capacity::<Int>(1));
1938 assert_eq!(2 + 4, max_array_capacity::<Int>(2));
1939 assert_eq!(2 + 4 + 8, max_array_capacity::<Int>(3));
1940 assert_eq!(2 + 4 + 8 + 16, max_array_capacity::<Int>(4));
1941 assert_eq!(2 + 4 + 8 + 16 + 32, max_array_capacity::<Int>(5));
1942 assert_eq!(2 + 4 + 8 + 16 + 32 + 64, max_array_capacity::<Int>(6));
1943 assert_eq!(2 + 4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<Int>(7),);
1944 }
1945
1946 #[test]
1947 fn array_capacity_string_reference() {
1948 assert_eq!(4, max_array_capacity::<StringRef>(1));
1949 assert_eq!(4 + 8, max_array_capacity::<StringRef>(2));
1950 assert_eq!(4 + 8 + 16, max_array_capacity::<StringRef>(3));
1951 assert_eq!(4 + 8 + 16 + 32, max_array_capacity::<StringRef>(4));
1952 assert_eq!(4 + 8 + 16 + 32 + 64, max_array_capacity::<StringRef>(5));
1953 assert_eq!(4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<StringRef>(6));
1954 assert_eq!(4 + 8 + 16 + 32 + 64 + 128 + 256, max_array_capacity::<StringRef>(7));
1955 }
1956
1957 #[fuchsia::test]
1958 fn set_parent_and_name() {
1959 let (mut container, _storage) =
1960 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1961 let mut block =
1962 get_reserved(&mut container).become_node(BlockIndex::new(1), BlockIndex::new(2));
1963 assert_eq!(*block.name_index(), 1);
1964 assert_eq!(*block.parent_index(), 2);
1965 block.set_name(BlockIndex::new(3));
1966 block.set_parent(BlockIndex::new(4));
1967 assert_eq!(*block.name_index(), 3);
1968 assert_eq!(*block.parent_index(), 4);
1969 }
1970
1971 fn get_header(container: &mut Container, size: usize) -> Block<&mut Container, Header> {
1972 get_reserved(container).become_header(size).unwrap()
1973 }
1974
1975 fn get_reserved(container: &mut Container) -> Block<&mut Container, Reserved> {
1976 get_reserved_of_order(container, 1)
1977 }
1978
1979 fn get_reserved_of_order(
1980 container: &mut Container,
1981 order: u8,
1982 ) -> Block<&mut Container, Reserved> {
1983 let block = Block::free(container, BlockIndex::EMPTY, order, BlockIndex::new(0)).unwrap();
1984 block.become_reserved()
1985 }
1986}