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(|i| BlockIndex::new(*i))
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).copied()
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).copied()
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).copied()
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 mut bytes = name.as_bytes();
741 let max_len = utils::payload_size_for_order(self.order());
742 if bytes.len() > max_len {
743 bytes = &bytes[..min(bytes.len(), max_len)];
744 while bytes[bytes.len() - 1] & 0x80 != 0 {
746 bytes = &bytes[..bytes.len() - 1];
747 }
748 }
749 HeaderFields::set_block_type(&mut self, BlockType::Name as u8);
750 HeaderFields::set_name_length(&mut self, u16::from_usize(bytes.len()).unwrap());
752 self.write_payload_from_bytes(bytes);
753 Block { index: self.index, container: self.container, _phantom: PhantomData }
754 }
755
756 pub fn become_link(
758 mut self,
759 name_index: BlockIndex,
760 parent_index: BlockIndex,
761 content_index: BlockIndex,
762 disposition_flags: LinkNodeDisposition,
763 ) -> Block<T, Link> {
764 self.write_value_header(BlockType::LinkValue, name_index, parent_index);
765 PayloadFields::set_value(&mut self, 0);
766 PayloadFields::set_content_index(&mut self, *content_index);
767 PayloadFields::set_disposition_flags(&mut self, disposition_flags as u8);
768 Block { index: self.index, container: self.container, _phantom: PhantomData }
769 }
770
771 pub fn become_array_value<S: ArraySlotKind>(
773 mut self,
774 slots: usize,
775 format: ArrayFormat,
776 name_index: BlockIndex,
777 parent_index: BlockIndex,
778 ) -> Result<Block<T, Array<S>>, Error> {
779 if S::block_type() == BlockType::StringReference && format != ArrayFormat::Default {
780 return Err(Error::InvalidArrayType(self.index));
781 }
782 let order = self.order();
783 let max_capacity = max_array_capacity::<S>(order);
784
785 if slots > max_capacity {
786 return Err(Error::array_capacity_exceeded(slots, order, max_capacity));
787 }
788 self.write_value_header(BlockType::ArrayValue, name_index, parent_index);
789 PayloadFields::set_value(&mut self, 0);
790 PayloadFields::set_array_entry_type(&mut self, S::block_type() as u8);
791 PayloadFields::set_array_flags(&mut self, format as u8);
792 PayloadFields::set_array_slots_count(&mut self, slots as u8);
793 let mut this =
794 Block { index: self.index, container: self.container, _phantom: PhantomData };
795 this.clear(0);
796 Ok(this)
797 }
798
799 #[cfg_attr(debug_assertions, track_caller)]
801 fn write_value_header(
802 &mut self,
803 block_type: BlockType,
804 name_index: BlockIndex,
805 parent_index: BlockIndex,
806 ) {
807 debug_assert!(block_type.is_any_value(), "Unexpected block: {block_type}");
808 HeaderFields::set_block_type(self, block_type as u8);
809 HeaderFields::set_value_name_index(self, *name_index);
810 HeaderFields::set_value_parent_index(self, *parent_index);
811 }
812}
813
814impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Header> {
815 #[doc(hidden)]
818 pub fn set_magic(&mut self, value: u32) {
819 HeaderFields::set_header_magic(self, value);
820 }
821
822 pub fn set_vmo_size(&mut self, size: u32) -> Result<(), Error> {
825 if self.order() != constants::HEADER_ORDER {
826 return Ok(());
827 }
828 match self.container.get_value_mut((self.index + 1).offset()) {
829 Some(value) => *value = size,
830 None => return Err(Error::SizeNotWritten(size)),
831 }
832 Ok(())
833 }
834
835 pub fn freeze(&mut self) -> u64 {
837 let value = PayloadFields::value(self);
838 PayloadFields::set_value(self, constants::VMO_FROZEN);
839 value
840 }
841
842 pub fn thaw(&mut self, generation: u64) {
844 PayloadFields::set_value(self, generation)
845 }
846
847 pub fn lock(&mut self) {
849 self.check_locked(false);
850 self.increment_generation_count();
851 fence(Ordering::Acquire);
852 }
853
854 pub fn unlock(&mut self) {
856 self.check_locked(true);
857 fence(Ordering::Release);
858 self.increment_generation_count();
859 }
860
861 fn increment_generation_count(&mut self) {
863 let value = PayloadFields::value(self);
864 let new_value = value.wrapping_add(1);
866 PayloadFields::set_value(self, new_value);
867 }
868}
869
870impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Node> {
871 pub fn become_tombstone(mut self) -> Block<T, Tombstone> {
873 HeaderFields::set_block_type(&mut self, BlockType::Tombstone as u8);
874 HeaderFields::set_tombstone_empty(&mut self, 0);
875 Block { index: self.index, container: self.container, _phantom: PhantomData }
876 }
877
878 pub fn set_child_count(&mut self, count: u64) {
880 PayloadFields::set_value(self, count);
881 }
882}
883
884impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, S: ArraySlotKind>
885 Block<T, Array<S>>
886{
887 pub fn clear(&mut self, start_slot_index: usize) {
889 let array_slots = self.slots() - start_slot_index;
890 let type_size = self.entry_type_size().unwrap();
894 let offset = (self.index + 1).offset() + start_slot_index * type_size;
895 if let Some(slice) = self.container.get_slice_mut_at(offset, array_slots * type_size) {
896 slice.fill(0);
897 }
898 }
899}
900
901impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes>
902 Block<T, Array<StringRef>>
903{
904 pub fn set_string_slot(&mut self, slot_index: usize, string_index: BlockIndex) {
906 if slot_index >= self.slots() {
907 return;
908 }
909 let type_size = StringRef::array_entry_type_size();
911 self.container.set_value((self.index + 1).offset() + slot_index * type_size, *string_index);
912 }
913}
914
915impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Array<Int>> {
916 pub fn set(&mut self, slot_index: usize, value: i64) {
918 if slot_index >= self.slots() {
919 return;
920 }
921 let type_size = Int::array_entry_type_size();
922 self.container.set_value((self.index + 1).offset() + slot_index * type_size, value);
923 }
924}
925
926impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes>
927 Block<T, Array<Double>>
928{
929 pub fn set(&mut self, slot_index: usize, value: f64) {
931 if slot_index >= self.slots() {
932 return;
933 }
934 let type_size = Double::array_entry_type_size();
935 self.container.set_value((self.index + 1).offset() + slot_index * type_size, value);
936 }
937}
938
939impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Array<Uint>> {
940 pub fn set(&mut self, slot_index: usize, value: u64) {
942 if slot_index >= self.slots() {
943 return;
944 }
945 let type_size = Uint::array_entry_type_size();
946 self.container.set_value((self.index + 1).offset() + slot_index * type_size, value);
947 }
948}
949
950impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Extent> {
951 pub fn set_next_index(&mut self, next_extent_index: BlockIndex) {
953 HeaderFields::set_extent_next_index(self, *next_extent_index);
954 }
955
956 pub fn set_contents(&mut self, value: &[u8]) -> usize {
958 let order = self.order();
959 let max_bytes = utils::payload_size_for_order(order);
960 let mut bytes = value;
961 if bytes.len() > max_bytes {
962 bytes = &bytes[..min(bytes.len(), max_bytes)];
963 }
964 self.write_payload_from_bytes(bytes);
965 bytes.len()
966 }
967}
968
969impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, StringRef> {
970 pub fn set_next_index(&mut self, next_extent_index: BlockIndex) {
972 HeaderFields::set_extent_next_index(self, *next_extent_index);
973 }
974
975 pub fn set_total_length(&mut self, length: u32) {
977 PayloadFields::set_property_total_length(self, length);
978 }
979
980 pub fn increment_ref_count(&mut self) -> Result<(), Error> {
982 let cur = HeaderFields::string_reference_count(self);
983 if cur < constants::MAX_REFERENCE_COUNT {
984 HeaderFields::set_string_reference_count(self, cur + 1);
985 }
986 Ok(())
987 }
988
989 pub fn decrement_ref_count(&mut self) -> Result<(), Error> {
991 let cur = HeaderFields::string_reference_count(self);
992 if cur < constants::MAX_REFERENCE_COUNT {
993 let new_count = cur.checked_sub(1).ok_or(Error::InvalidReferenceCount)?;
994 HeaderFields::set_string_reference_count(self, new_count);
995 }
996 Ok(())
997 }
998
999 pub fn write_inline(&mut self, value: &[u8]) -> usize {
1003 let payload_offset = self.payload_offset();
1004 self.set_total_length(value.len() as u32);
1005 let max_len = utils::payload_size_for_order(self.order())
1006 - constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES;
1007 let bytes = min(value.len(), max_len);
1010 let to_inline = &value[..bytes];
1011 self.container.copy_from_slice_at(
1012 payload_offset + constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES,
1013 to_inline,
1014 );
1015 bytes
1016 }
1017}
1018
1019impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Double> {
1020 pub fn set(&mut self, value: f64) {
1022 PayloadFields::set_value(self, value.to_bits());
1023 }
1024}
1025
1026impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Int> {
1027 pub fn set(&mut self, value: i64) {
1029 PayloadFields::set_value(self, LittleEndian::read_u64(&value.to_le_bytes()));
1030 }
1031}
1032
1033impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Uint> {
1034 pub fn set(&mut self, value: u64) {
1036 PayloadFields::set_value(self, value);
1037 }
1038}
1039
1040impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Bool> {
1041 pub fn set(&mut self, value: bool) {
1043 PayloadFields::set_value(self, value as u64);
1044 }
1045}
1046
1047impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Buffer> {
1048 pub fn set_total_length(&mut self, length: u32) {
1050 PayloadFields::set_property_total_length(self, length);
1051 }
1052
1053 pub fn set_extent_index(&mut self, index: BlockIndex) {
1055 PayloadFields::set_property_extent_index(self, *index);
1058 }
1059}
1060
1061impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Tombstone> {
1062 pub fn set_child_count(&mut self, count: u64) {
1064 PayloadFields::set_value(self, count);
1065 }
1066}
1067
1068impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, K: ValueBlockKind>
1069 Block<T, K>
1070{
1071 pub fn set_parent(&mut self, new_parent_index: BlockIndex) {
1072 HeaderFields::set_value_parent_index(self, *new_parent_index);
1073 }
1074}
1075
1076fn max_array_capacity<S: ArraySlotKind>(order: u8) -> usize {
1078 array_capacity(S::array_entry_type_size(), order)
1079}
1080
1081fn array_capacity(slot_size: usize, order: u8) -> usize {
1082 (utils::order_to_size(order)
1083 - constants::HEADER_SIZE_BYTES
1084 - constants::ARRAY_PAYLOAD_METADATA_SIZE_BYTES)
1085 / slot_size
1086}
1087
1088pub mod testing {
1089 use super::*;
1090
1091 pub fn override_header<T: WriteBytes + ReadBytes, K: BlockKind>(
1092 block: &mut Block<&mut T, K>,
1093 value: u64,
1094 ) {
1095 block.container.set_value(block.header_offset(), value);
1096 }
1097
1098 pub fn override_payload<T: WriteBytes + ReadBytes, K: BlockKind>(
1099 block: &mut Block<&mut T, K>,
1100 value: u64,
1101 ) {
1102 block.container.set_value(block.payload_offset(), value);
1103 }
1104}
1105
1106#[cfg(test)]
1107mod tests {
1108 use super::*;
1109 use crate::{Container, CopyBytes};
1110
1111 macro_rules! assert_8_bytes {
1112 ($container:ident, $offset:expr, $expected:expr) => {
1113 let slice = $container.get_slice_at($offset, 8).unwrap();
1114 assert_eq!(slice, &$expected);
1115 };
1116 }
1117
1118 #[fuchsia::test]
1119 fn test_new_free() {
1120 let (mut container, _storage) =
1121 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1122 assert!(Block::free(&mut container, 3.into(), constants::NUM_ORDERS, 1.into()).is_err());
1123
1124 let res = Block::free(&mut container, BlockIndex::EMPTY, 3, 1.into());
1125 assert!(res.is_ok());
1126 let block = res.unwrap();
1127 assert_eq!(*block.index(), 0);
1128 assert_eq!(block.order(), 3);
1129 assert_eq!(*block.free_next_index(), 1);
1130 assert_eq!(block.block_type(), Some(BlockType::Free));
1131 assert_8_bytes!(container, 0, [0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]);
1132 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1133 }
1134
1135 #[fuchsia::test]
1136 fn test_set_order() {
1137 let (mut container, _storage) =
1138 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1139 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1140 assert!(block.set_order(3).is_ok());
1141 assert_eq!(block.order(), 3);
1142 }
1143
1144 #[fuchsia::test]
1145 fn test_become_reserved() {
1146 let (mut container, _storage) =
1147 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1148 let block = Block::free(&mut container, BlockIndex::EMPTY, 1, 2.into()).unwrap();
1149 let block = block.become_reserved();
1150 assert_eq!(block.block_type(), Some(BlockType::Reserved));
1151 assert_8_bytes!(container, 0, [0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1152 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1153 }
1154
1155 #[fuchsia::test]
1156 fn test_become_string_reference() {
1157 let (mut container, _storage) =
1158 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1159 let block = get_reserved(&mut container).become_string_reference();
1160 assert_eq!(block.block_type(), Some(BlockType::StringReference));
1161 assert_eq!(*block.next_extent(), 0);
1162 assert_eq!(block.reference_count(), 0);
1163 assert_eq!(block.total_length(), 0);
1164 assert_eq!(block.inline_data().unwrap(), Vec::<u8>::new());
1165 assert_8_bytes!(container, 0, [0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1166 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1167 }
1168
1169 #[fuchsia::test]
1170 fn test_inline_string_reference() {
1171 let (mut container, _storage) =
1172 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1173 let mut block = get_reserved(&mut container);
1174 block.set_order(0).unwrap();
1175 let mut block = block.become_string_reference();
1176
1177 assert_eq!(block.write_inline("ab".as_bytes()), 2);
1178 assert_eq!(block.reference_count(), 0);
1179 assert_eq!(block.total_length(), 2);
1180 assert_eq!(block.order(), 0);
1181 assert_eq!(*block.next_extent(), 0);
1182 assert_eq!(block.inline_data().unwrap(), "ab".as_bytes());
1183
1184 assert_eq!(block.write_inline("abcd".as_bytes()), 4);
1185 assert_eq!(block.reference_count(), 0);
1186 assert_eq!(block.total_length(), 4);
1187 assert_eq!(block.order(), 0);
1188 assert_eq!(*block.next_extent(), 0);
1189 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1190
1191 assert_eq!(
1192 block.write_inline("abcdefghijklmnopqrstuvwxyz".as_bytes()),
1193 4 );
1195 assert_eq!(block.reference_count(), 0);
1196 assert_eq!(block.total_length(), 26);
1197 assert_eq!(block.order(), 0);
1198 assert_eq!(*block.next_extent(), 0);
1199 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1200
1201 assert_eq!(block.write_inline("abcdef".as_bytes()), 4);
1202 assert_eq!(block.reference_count(), 0);
1203 assert_eq!(block.total_length(), 6);
1204 assert_eq!(block.order(), 0);
1205 assert_eq!(*block.next_extent(), 0);
1206 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1207 }
1208
1209 #[fuchsia::test]
1210 fn test_string_reference_count() {
1211 let (mut container, _storage) =
1212 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1213 let mut block = get_reserved(&mut container);
1214 block.set_order(0).unwrap();
1215 let mut block = block.become_string_reference();
1216 assert_eq!(block.reference_count(), 0);
1217
1218 assert!(block.increment_ref_count().is_ok());
1219 assert_eq!(block.reference_count(), 1);
1220
1221 assert!(block.decrement_ref_count().is_ok());
1222 assert_eq!(block.reference_count(), 0);
1223
1224 assert!(block.decrement_ref_count().is_err());
1225 assert_eq!(block.reference_count(), 0);
1226
1227 HeaderFields::set_string_reference_count(&mut block, constants::MAX_REFERENCE_COUNT);
1228 assert_eq!(block.reference_count(), constants::MAX_REFERENCE_COUNT);
1229
1230 assert!(block.increment_ref_count().is_ok());
1231 assert_eq!(block.reference_count(), constants::MAX_REFERENCE_COUNT);
1232
1233 assert!(block.decrement_ref_count().is_ok());
1234 assert_eq!(block.reference_count(), constants::MAX_REFERENCE_COUNT);
1235 }
1236
1237 #[fuchsia::test]
1238 fn test_become_header() {
1239 let (mut container, _storage) =
1240 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1241 let block =
1242 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1243 assert_eq!(block.block_type(), Some(BlockType::Header));
1244 assert_eq!(*block.index(), 0);
1245 assert_eq!(block.order(), constants::HEADER_ORDER);
1246 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1247 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1248 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::MIN_ORDER_SIZE * 2);
1249 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1250 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1251 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1252 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1253 }
1254
1255 #[fuchsia::test]
1256 fn test_header_without_size() {
1257 let (mut container, _storage) =
1258 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1259 let block =
1260 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1261 assert_eq!(block.order(), constants::HEADER_ORDER);
1262 assert!(block.vmo_size().unwrap().is_some());
1263
1264 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1265
1266 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1268 assert!(block.set_order(0).is_ok());
1269 assert_eq!(block.vmo_size().unwrap(), None);
1270 assert!(block.set_vmo_size(123456789).is_ok());
1272 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1273 }
1274
1275 #[fuchsia::test]
1276 fn test_freeze_thaw_header() {
1277 let (mut container, _storage) =
1278 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1279 let block =
1280 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1281 assert_eq!(block.block_type(), Some(BlockType::Header));
1282 assert_eq!(*block.index(), 0);
1283 assert_eq!(block.order(), constants::HEADER_ORDER);
1284 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1285 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1286 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1287 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1288 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1289 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1290
1291 let old = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).freeze();
1292 assert_8_bytes!(container, 8, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1293 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1294 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1295 container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).thaw(old);
1296 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1297 assert_8_bytes!(container, 16, [0x020, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1298 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1299 }
1300
1301 #[fuchsia::test]
1302 #[should_panic]
1303 fn test_cant_unlock_locked_header() {
1304 let (mut container, _storage) =
1305 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1306 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1307 block.unlock();
1309 }
1310
1311 #[fuchsia::test]
1312 #[should_panic]
1313 fn test_cant_lock_locked_header() {
1314 let (mut container, _storage) =
1315 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1316 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1317 block.lock();
1318 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1320 block.lock();
1321 }
1322
1323 #[fuchsia::test]
1324 #[should_panic]
1325 fn test_header_overflow() {
1326 let (mut container, _storage) =
1329 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1330 container.set_value(8, u64::MAX);
1331 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1332 block.lock();
1333 }
1334
1335 #[fuchsia::test]
1336 fn test_lock_unlock_header() {
1337 let (mut container, _storage) =
1338 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1339 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1340 block.lock();
1341 assert!(block.is_locked());
1342 assert_eq!(block.generation_count(), 1);
1343 let header_bytes: [u8; 8] = [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50];
1344 assert_8_bytes!(container, 0, header_bytes[..]);
1345 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1346 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1347 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1348 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1349 block.unlock();
1350 assert!(!block.is_locked());
1351 assert_eq!(block.generation_count(), 2);
1352 assert_8_bytes!(container, 0, header_bytes[..]);
1353 assert_8_bytes!(container, 8, [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1354 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1355 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1356
1357 container.set_value(8, u64::MAX);
1359 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1360 block.unlock();
1361 assert_eq!(block.generation_count(), 0);
1362 assert_8_bytes!(container, 0, header_bytes[..]);
1363 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1364 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1365 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1366 }
1367
1368 #[fuchsia::test]
1369 fn test_header_vmo_size() {
1370 let (mut container, _storage) =
1371 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1372 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1373 assert!(block.set_vmo_size(constants::DEFAULT_VMO_SIZE_BYTES.try_into().unwrap()).is_ok());
1374 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1375 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1376 assert_8_bytes!(container, 16, [0x00, 0x00, 0x4, 0x00, 0x00, 0x00, 0x00, 0x00]);
1377 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1378 let block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1379 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::DEFAULT_VMO_SIZE_BYTES);
1380 }
1381
1382 #[fuchsia::test]
1383 fn test_become_tombstone() {
1384 let (mut container, _storage) =
1385 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1386 let mut block = get_reserved(&mut container).become_node(2.into(), 3.into());
1387 block.set_child_count(4);
1388 let block = block.become_tombstone();
1389 assert_eq!(block.block_type(), Some(BlockType::Tombstone));
1390 assert_eq!(block.child_count(), 4);
1391 assert_8_bytes!(container, 0, [0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1392 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1393 }
1394
1395 #[fuchsia::test]
1396 fn test_child_count() {
1397 let (mut container, _storage) =
1398 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1399 let _ = get_reserved(&mut container).become_node(2.into(), 3.into());
1400 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1401 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1402 let mut block = container.block_at_unchecked_mut::<Node>(BlockIndex::EMPTY);
1403 block.set_child_count(4);
1404 assert_eq!(block.child_count(), 4);
1405 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1406 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1407 }
1408
1409 #[fuchsia::test]
1410 fn test_free() {
1411 let (mut container, _storage) =
1412 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1413 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1414 block.set_free_next_index(3.into());
1415 assert_eq!(*block.free_next_index(), 3);
1416 assert_8_bytes!(container, 0, [0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1417 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1418 }
1419
1420 #[fuchsia::test]
1421 fn test_extent() {
1422 let (mut container, _storage) =
1423 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1424 let block = get_reserved(&mut container).become_extent(3.into());
1425 assert_eq!(block.block_type(), Some(BlockType::Extent));
1426 assert_eq!(*block.next_extent(), 3);
1427 assert_8_bytes!(container, 0, [0x01, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1428 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1429
1430 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1431 assert_eq!(block.set_contents("test-rust-inspect".as_bytes()), 17);
1432 assert_eq!(
1433 String::from_utf8(block.contents().unwrap().to_vec()).unwrap(),
1434 "test-rust-inspect\0\0\0\0\0\0\0"
1435 );
1436 let slice = container.get_slice_at(8, 17).unwrap();
1437 assert_eq!(slice, "test-rust-inspect".as_bytes());
1438 let slice = container.get_slice_at(25, 7).unwrap();
1439 assert_eq!(slice, &[0, 0, 0, 0, 0, 0, 0]);
1440
1441 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1442 block.set_next_index(4.into());
1443 assert_eq!(*block.next_extent(), 4);
1444 }
1445
1446 #[fuchsia::test]
1447 fn test_double_value() {
1448 let (mut container, _storage) =
1449 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1450 let block = get_reserved(&mut container).become_double_value(1.0, 2.into(), 3.into());
1451 assert_eq!(block.block_type(), Some(BlockType::DoubleValue));
1452 assert_eq!(*block.name_index(), 2);
1453 assert_eq!(*block.parent_index(), 3);
1454 assert_eq!(block.value(), 1.0);
1455 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1456 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f]);
1457
1458 let mut block = container.block_at_unchecked_mut::<Double>(BlockIndex::EMPTY);
1459 block.set(5.0);
1460 assert_eq!(block.value(), 5.0);
1461 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1462 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40]);
1463 }
1464
1465 #[fuchsia::test]
1466 fn test_int_value() {
1467 let (mut container, _storage) =
1468 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1469 let block = get_reserved(&mut container).become_int_value(1, 2.into(), 3.into());
1470 assert_eq!(block.block_type(), Some(BlockType::IntValue));
1471 assert_eq!(*block.name_index(), 2);
1472 assert_eq!(*block.parent_index(), 3);
1473 assert_eq!(block.value(), 1);
1474 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1475 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1476
1477 let mut block = container.block_at_unchecked_mut::<Int>(BlockIndex::EMPTY);
1478 block.set(-5);
1479 assert_eq!(block.value(), -5);
1480 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1481 assert_8_bytes!(container, 8, [0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
1482 }
1483
1484 #[fuchsia::test]
1485 fn test_uint_value() {
1486 let (mut container, _storage) =
1487 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1488 let block = get_reserved(&mut container).become_uint_value(1, 2.into(), 3.into());
1489 assert_eq!(block.block_type(), Some(BlockType::UintValue));
1490 assert_eq!(*block.name_index(), 2);
1491 assert_eq!(*block.parent_index(), 3);
1492 assert_eq!(block.value(), 1);
1493 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1494 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1495
1496 let mut block = container.block_at_unchecked_mut::<Uint>(BlockIndex::EMPTY);
1497 block.set(5);
1498 assert_eq!(block.value(), 5);
1499 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1500 assert_8_bytes!(container, 8, [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1501 }
1502
1503 #[fuchsia::test]
1504 fn test_bool_value() {
1505 let (mut container, _storage) =
1506 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1507 let block = get_reserved(&mut container).become_bool_value(false, 2.into(), 3.into());
1508 assert_eq!(block.block_type(), Some(BlockType::BoolValue));
1509 assert_eq!(*block.name_index(), 2);
1510 assert_eq!(*block.parent_index(), 3);
1511 assert!(!block.value());
1512 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1513 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1514
1515 let mut block = container.block_at_unchecked_mut::<Bool>(BlockIndex::EMPTY);
1516 block.set(true);
1517 assert!(block.value());
1518 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1519 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1520 }
1521
1522 #[fuchsia::test]
1523 fn test_become_node() {
1524 let (mut container, _storage) =
1525 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1526 let block = get_reserved(&mut container).become_node(2.into(), 3.into());
1527 assert_eq!(block.block_type(), Some(BlockType::NodeValue));
1528 assert_eq!(*block.name_index(), 2);
1529 assert_eq!(*block.parent_index(), 3);
1530 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1531 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1532 }
1533
1534 #[fuchsia::test]
1535 fn test_property() {
1536 let (mut container, _storage) =
1537 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1538 let block =
1539 get_reserved(&mut container).become_property(2.into(), 3.into(), PropertyFormat::Bytes);
1540 assert_eq!(block.block_type(), Some(BlockType::BufferValue));
1541 assert_eq!(*block.name_index(), 2);
1542 assert_eq!(*block.parent_index(), 3);
1543 assert_eq!(block.format(), Some(PropertyFormat::Bytes));
1544 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1545 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1546
1547 let (mut bad_container, _storage) =
1548 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1549 let mut bad_format_bytes = [0u8; constants::MIN_ORDER_SIZE];
1550 bad_format_bytes[15] = 0x30;
1551 bad_container.copy_from_slice(&bad_format_bytes);
1552 let bad_block = Block::<_, Buffer>::new(&bad_container, BlockIndex::EMPTY);
1553 assert_eq!(bad_block.format(), None);
1554
1555 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1556 block.set_extent_index(4.into());
1557 assert_eq!(*block.extent_index(), 4);
1558 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1559 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1560
1561 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1562 block.set_total_length(10);
1563 assert_eq!(block.total_length(), 10);
1564 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1565 assert_8_bytes!(container, 8, [0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1566 }
1567
1568 #[fuchsia::test]
1569 fn test_name() {
1570 let (mut container, _storage) =
1571 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1572 let block = get_reserved(&mut container).become_name("test-rust-inspect");
1573 assert_eq!(block.block_type(), Some(BlockType::Name));
1574 assert_eq!(block.length(), 17);
1575 assert_eq!(block.contents().unwrap(), "test-rust-inspect");
1576 assert_8_bytes!(container, 0, [0x01, 0x09, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
1577 let slice = container.get_slice_at(8, 17).unwrap();
1578 assert_eq!(slice, "test-rust-inspect".as_bytes());
1579 let slice = container.get_slice_at(25, 7).unwrap();
1580 assert_eq!(slice, [0, 0, 0, 0, 0, 0, 0]);
1581
1582 *container.get_value_mut::<u8>(24).unwrap() = 0xff;
1583 let bad_block = Block::<_, Name>::new(&container, BlockIndex::EMPTY);
1584 assert_eq!(bad_block.length(), 17); assert!(bad_block.contents().is_err()); let (mut container, _storage) =
1590 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1591 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstuvwxyz");
1592 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstuvwx");
1593
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("😀abcdefghijklmnopqrstuvwxyz");
1597 assert_eq!(block.contents().unwrap(), "😀abcdefghijklmnopqrst");
1598
1599 let (mut container, _storage) =
1600 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1601 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstu😀");
1602 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstu");
1603 let byte = container.get_value::<u8>(31).unwrap();
1604 assert_eq!(*byte, 0);
1605 }
1606
1607 #[fuchsia::test]
1608 fn test_invalid_type_for_array() {
1609 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1610 container.get_slice_mut_at(24, 2048 - 24).unwrap().fill(14);
1611
1612 fn become_array<S: ArraySlotKind>(
1613 container: &mut Container,
1614 format: ArrayFormat,
1615 ) -> Result<Block<&mut Container, Array<S>>, Error> {
1616 get_reserved_of_order(container, 4).become_array_value::<S>(
1617 4,
1618 format,
1619 BlockIndex::EMPTY,
1620 BlockIndex::EMPTY,
1621 )
1622 }
1623
1624 assert!(become_array::<Int>(&mut container, ArrayFormat::Default).is_ok());
1625 assert!(become_array::<Uint>(&mut container, ArrayFormat::Default).is_ok());
1626 assert!(become_array::<Double>(&mut container, ArrayFormat::Default).is_ok());
1627 assert!(become_array::<StringRef>(&mut container, ArrayFormat::Default).is_ok());
1628
1629 for format in [ArrayFormat::LinearHistogram, ArrayFormat::ExponentialHistogram] {
1630 assert!(become_array::<Int>(&mut container, format).is_ok());
1631 assert!(become_array::<Uint>(&mut container, format).is_ok());
1632 assert!(become_array::<Double>(&mut container, format).is_ok());
1633 assert!(become_array::<StringRef>(&mut container, format).is_err());
1634 }
1635 }
1636
1637 #[fuchsia::test]
1643 fn test_string_arrays() {
1644 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1645 container.get_slice_mut_at(48, 2048 - 48).unwrap().fill(14);
1646
1647 let parent_index = BlockIndex::new(0);
1648 let name_index = BlockIndex::new(1);
1649 let mut block = get_reserved(&mut container)
1650 .become_array_value::<StringRef>(4, ArrayFormat::Default, name_index, parent_index)
1651 .unwrap();
1652
1653 for i in 0..4 {
1654 block.set_string_slot(i, ((i + 4) as u32).into());
1655 }
1656
1657 for i in 0..4 {
1658 let read_index = block.get_string_index_at(i).unwrap();
1659 assert_eq!(*read_index, (i + 4) as u32);
1660 }
1661
1662 assert_8_bytes!(
1663 container,
1664 0,
1665 [
1666 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
1669 ]
1670 );
1671 assert_8_bytes!(container, 8, [0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1672 for i in 0..4 {
1673 let slice = container.get_slice_at(16 + (i * 4), 4).unwrap();
1674 assert_eq!(slice, [(i as u8 + 4), 0x00, 0x00, 0x00]);
1675 }
1676 }
1677
1678 #[fuchsia::test]
1679 fn become_array() {
1680 let (mut container, _storage) = Container::read_and_write(128).unwrap();
1682 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1683
1684 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1685 .unwrap()
1686 .become_reserved()
1687 .become_array_value::<Int>(
1688 14,
1689 ArrayFormat::Default,
1690 BlockIndex::EMPTY,
1691 BlockIndex::EMPTY,
1692 )
1693 .unwrap();
1694 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1695 slice
1696 .iter()
1697 .enumerate()
1698 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1699
1700 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1701 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1702 .unwrap()
1703 .become_reserved()
1704 .become_array_value::<Int>(
1705 14,
1706 ArrayFormat::LinearHistogram,
1707 BlockIndex::EMPTY,
1708 BlockIndex::EMPTY,
1709 )
1710 .unwrap();
1711 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1712 slice
1713 .iter()
1714 .enumerate()
1715 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1716
1717 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1718 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1719 .unwrap()
1720 .become_reserved()
1721 .become_array_value::<Int>(
1722 14,
1723 ArrayFormat::ExponentialHistogram,
1724 BlockIndex::EMPTY,
1725 BlockIndex::EMPTY,
1726 )
1727 .unwrap();
1728 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1729 slice
1730 .iter()
1731 .enumerate()
1732 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1733
1734 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1735 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1736 .unwrap()
1737 .become_reserved()
1738 .become_array_value::<StringRef>(
1739 28,
1740 ArrayFormat::Default,
1741 BlockIndex::EMPTY,
1742 BlockIndex::EMPTY,
1743 )
1744 .unwrap();
1745 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1746 slice
1747 .iter()
1748 .enumerate()
1749 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1750 }
1751
1752 #[fuchsia::test]
1753 fn uint_array_value() {
1754 let (mut container, _storage) =
1755 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1756 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1757 .unwrap()
1758 .become_reserved()
1759 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1760 .unwrap();
1761
1762 assert_eq!(block.block_type(), Some(BlockType::ArrayValue));
1763 assert_eq!(*block.parent_index(), 2);
1764 assert_eq!(*block.name_index(), 3);
1765 assert_eq!(block.format(), Some(ArrayFormat::LinearHistogram));
1766 assert_eq!(block.slots(), 4);
1767 assert_eq!(block.entry_type(), Some(BlockType::UintValue));
1768
1769 for i in 0..4 {
1770 block.set(i, (i as u64 + 1) * 5);
1771 }
1772 block.set(4, 3);
1773 block.set(7, 5);
1774
1775 assert_8_bytes!(container, 0, [0x02, 0x0b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00]);
1776 assert_8_bytes!(container, 8, [0x15, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1777 for i in 0..4 {
1778 assert_8_bytes!(
1779 container,
1780 8 * (i + 2),
1781 [(i as u8 + 1) * 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1782 );
1783 }
1784
1785 let (mut bad_container, _storage) =
1786 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1787 let mut bad_bytes = [0u8; constants::MIN_ORDER_SIZE];
1788 container.copy_bytes(&mut bad_bytes[..]);
1789 bad_bytes[8] = 0x12; bad_container.copy_from_slice(&bad_bytes);
1791 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1792 assert_eq!(bad_block.format(), Some(ArrayFormat::LinearHistogram));
1793 assert_eq!(bad_block.entry_type(), None);
1795
1796 bad_bytes[8] = 0xef; bad_container.copy_from_slice(&bad_bytes);
1798 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1799 assert_eq!(bad_block.format(), None);
1800 assert_eq!(bad_block.entry_type(), None);
1801
1802 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1803 for i in 0..4 {
1804 assert_eq!(block.get(i), Some((i as u64 + 1) * 5));
1805 }
1806 assert_eq!(block.get(4), None);
1807 }
1808
1809 #[fuchsia::test]
1810 fn array_slots_bigger_than_block_order() {
1811 let (mut container, _storage) =
1812 Container::read_and_write(constants::MAX_ORDER_SIZE).unwrap();
1813 assert!(
1816 Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1817 .unwrap()
1818 .become_reserved()
1819 .become_array_value::<Int>(257, ArrayFormat::Default, 1.into(), 2.into())
1820 .is_err()
1821 );
1822 assert!(
1823 Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1824 .unwrap()
1825 .become_reserved()
1826 .become_array_value::<Int>(254, ArrayFormat::Default, 1.into(), 2.into())
1827 .is_ok()
1828 );
1829
1830 assert!(
1833 Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1834 .unwrap()
1835 .become_reserved()
1836 .become_array_value::<Int>(8, ArrayFormat::Default, 1.into(), 2.into())
1837 .is_err()
1838 );
1839 assert!(
1840 Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1841 .unwrap()
1842 .become_reserved()
1843 .become_array_value::<Int>(6, ArrayFormat::Default, 1.into(), 2.into())
1844 .is_ok()
1845 );
1846 }
1847
1848 #[fuchsia::test]
1849 fn array_clear() {
1850 let (mut container, _storage) =
1851 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1852
1853 let sample = [0xff, 0xff, 0xff];
1855 container.copy_from_slice_at(48, &sample);
1856
1857 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1858 .unwrap()
1859 .become_reserved()
1860 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1861 .unwrap();
1862
1863 for i in 0..4 {
1864 block.set(i, (i + 1) as u64);
1865 }
1866
1867 block.clear(1);
1868
1869 assert_eq!(1, block.get(0).expect("get uint 0"));
1870 assert_8_bytes!(container, 16, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1871
1872 for i in 1..4 {
1873 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1874 assert_eq!(0, block.get(i).expect("get uint"));
1875 assert_8_bytes!(
1876 container,
1877 16 + (i * 8),
1878 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1879 );
1880 }
1881
1882 let slice = container.get_slice_at(48, 3).unwrap();
1884 assert_eq!(slice, &sample[..]);
1885 }
1886
1887 #[fuchsia::test]
1888 fn become_link() {
1889 let (mut container, _storage) =
1890 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1891 let block = get_reserved(&mut container).become_link(
1892 BlockIndex::new(1),
1893 BlockIndex::new(2),
1894 BlockIndex::new(3),
1895 LinkNodeDisposition::Inline,
1896 );
1897 assert_eq!(*block.name_index(), 1);
1898 assert_eq!(*block.parent_index(), 2);
1899 assert_eq!(*block.content_index(), 3);
1900 assert_eq!(block.block_type(), Some(BlockType::LinkValue));
1901 assert_eq!(block.link_node_disposition(), Some(LinkNodeDisposition::Inline));
1902 assert_8_bytes!(container, 0, [0x01, 0x0c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00]);
1903 assert_8_bytes!(container, 8, [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1904 }
1905
1906 #[test]
1907 fn array_capacity_numeric() {
1908 assert_eq!(2, max_array_capacity::<Int>(1));
1909 assert_eq!(2 + 4, max_array_capacity::<Int>(2));
1910 assert_eq!(2 + 4 + 8, max_array_capacity::<Int>(3));
1911 assert_eq!(2 + 4 + 8 + 16, max_array_capacity::<Int>(4));
1912 assert_eq!(2 + 4 + 8 + 16 + 32, max_array_capacity::<Int>(5));
1913 assert_eq!(2 + 4 + 8 + 16 + 32 + 64, max_array_capacity::<Int>(6));
1914 assert_eq!(2 + 4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<Int>(7),);
1915 }
1916
1917 #[test]
1918 fn array_capacity_string_reference() {
1919 assert_eq!(4, max_array_capacity::<StringRef>(1));
1920 assert_eq!(4 + 8, max_array_capacity::<StringRef>(2));
1921 assert_eq!(4 + 8 + 16, max_array_capacity::<StringRef>(3));
1922 assert_eq!(4 + 8 + 16 + 32, max_array_capacity::<StringRef>(4));
1923 assert_eq!(4 + 8 + 16 + 32 + 64, max_array_capacity::<StringRef>(5));
1924 assert_eq!(4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<StringRef>(6));
1925 assert_eq!(4 + 8 + 16 + 32 + 64 + 128 + 256, max_array_capacity::<StringRef>(7));
1926 }
1927
1928 fn get_header(container: &mut Container, size: usize) -> Block<&mut Container, Header> {
1929 get_reserved(container).become_header(size).unwrap()
1930 }
1931
1932 fn get_reserved(container: &mut Container) -> Block<&mut Container, Reserved> {
1933 get_reserved_of_order(container, 1)
1934 }
1935
1936 fn get_reserved_of_order(
1937 container: &mut Container,
1938 order: u8,
1939 ) -> Block<&mut Container, Reserved> {
1940 let block = Block::free(container, BlockIndex::EMPTY, order, BlockIndex::new(0)).unwrap();
1941 block.become_reserved()
1942 }
1943}