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::{fence, Ordering};
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, gen: u64) {
844 PayloadFields::set_value(self, gen)
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 let new_count = cur.checked_add(1).ok_or(Error::InvalidReferenceCount)?;
984 HeaderFields::set_string_reference_count(self, new_count);
985 Ok(())
986 }
987
988 pub fn decrement_ref_count(&mut self) -> Result<(), Error> {
990 let cur = HeaderFields::string_reference_count(self);
991 let new_count = cur.checked_sub(1).ok_or(Error::InvalidReferenceCount)?;
992 HeaderFields::set_string_reference_count(self, new_count);
993 Ok(())
994 }
995
996 pub fn write_inline(&mut self, value: &[u8]) -> usize {
1000 let payload_offset = self.payload_offset();
1001 self.set_total_length(value.len() as u32);
1002 let max_len = utils::payload_size_for_order(self.order())
1003 - constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES;
1004 let bytes = min(value.len(), max_len);
1007 let to_inline = &value[..bytes];
1008 self.container.copy_from_slice_at(
1009 payload_offset + constants::STRING_REFERENCE_TOTAL_LENGTH_BYTES,
1010 to_inline,
1011 );
1012 bytes
1013 }
1014}
1015
1016impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Double> {
1017 pub fn set(&mut self, value: f64) {
1019 PayloadFields::set_value(self, value.to_bits());
1020 }
1021}
1022
1023impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Int> {
1024 pub fn set(&mut self, value: i64) {
1026 PayloadFields::set_value(self, LittleEndian::read_u64(&value.to_le_bytes()));
1027 }
1028}
1029
1030impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Uint> {
1031 pub fn set(&mut self, value: u64) {
1033 PayloadFields::set_value(self, value);
1034 }
1035}
1036
1037impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Bool> {
1038 pub fn set(&mut self, value: bool) {
1040 PayloadFields::set_value(self, value as u64);
1041 }
1042}
1043
1044impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Buffer> {
1045 pub fn set_total_length(&mut self, length: u32) {
1047 PayloadFields::set_property_total_length(self, length);
1048 }
1049
1050 pub fn set_extent_index(&mut self, index: BlockIndex) {
1052 PayloadFields::set_property_extent_index(self, *index);
1055 }
1056}
1057
1058impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes> Block<T, Tombstone> {
1059 pub fn set_child_count(&mut self, count: u64) {
1061 PayloadFields::set_value(self, count);
1062 }
1063}
1064
1065impl<T: Deref<Target = Q> + DerefMut<Target = Q>, Q: WriteBytes + ReadBytes, K: ValueBlockKind>
1066 Block<T, K>
1067{
1068 pub fn set_parent(&mut self, new_parent_index: BlockIndex) {
1069 HeaderFields::set_value_parent_index(self, *new_parent_index);
1070 }
1071}
1072
1073fn max_array_capacity<S: ArraySlotKind>(order: u8) -> usize {
1075 array_capacity(S::array_entry_type_size(), order)
1076}
1077
1078fn array_capacity(slot_size: usize, order: u8) -> usize {
1079 (utils::order_to_size(order)
1080 - constants::HEADER_SIZE_BYTES
1081 - constants::ARRAY_PAYLOAD_METADATA_SIZE_BYTES)
1082 / slot_size
1083}
1084
1085pub mod testing {
1086 use super::*;
1087
1088 pub fn override_header<T: WriteBytes + ReadBytes, K: BlockKind>(
1089 block: &mut Block<&mut T, K>,
1090 value: u64,
1091 ) {
1092 block.container.set_value(block.header_offset(), value);
1093 }
1094
1095 pub fn override_payload<T: WriteBytes + ReadBytes, K: BlockKind>(
1096 block: &mut Block<&mut T, K>,
1097 value: u64,
1098 ) {
1099 block.container.set_value(block.payload_offset(), value);
1100 }
1101}
1102
1103#[cfg(test)]
1104mod tests {
1105 use super::*;
1106 use crate::{Container, CopyBytes};
1107
1108 macro_rules! assert_8_bytes {
1109 ($container:ident, $offset:expr, $expected:expr) => {
1110 let slice = $container.get_slice_at($offset, 8).unwrap();
1111 assert_eq!(slice, &$expected);
1112 };
1113 }
1114
1115 #[fuchsia::test]
1116 fn test_new_free() {
1117 let (mut container, _storage) =
1118 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1119 assert!(Block::free(&mut container, 3.into(), constants::NUM_ORDERS, 1.into()).is_err());
1120
1121 let res = Block::free(&mut container, BlockIndex::EMPTY, 3, 1.into());
1122 assert!(res.is_ok());
1123 let block = res.unwrap();
1124 assert_eq!(*block.index(), 0);
1125 assert_eq!(block.order(), 3);
1126 assert_eq!(*block.free_next_index(), 1);
1127 assert_eq!(block.block_type(), Some(BlockType::Free));
1128 assert_8_bytes!(container, 0, [0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]);
1129 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1130 }
1131
1132 #[fuchsia::test]
1133 fn test_set_order() {
1134 let (mut container, _storage) =
1135 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1136 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1137 assert!(block.set_order(3).is_ok());
1138 assert_eq!(block.order(), 3);
1139 }
1140
1141 #[fuchsia::test]
1142 fn test_become_reserved() {
1143 let (mut container, _storage) =
1144 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1145 let block = Block::free(&mut container, BlockIndex::EMPTY, 1, 2.into()).unwrap();
1146 let block = block.become_reserved();
1147 assert_eq!(block.block_type(), Some(BlockType::Reserved));
1148 assert_8_bytes!(container, 0, [0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1149 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1150 }
1151
1152 #[fuchsia::test]
1153 fn test_become_string_reference() {
1154 let (mut container, _storage) =
1155 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1156 let block = get_reserved(&mut container).become_string_reference();
1157 assert_eq!(block.block_type(), Some(BlockType::StringReference));
1158 assert_eq!(*block.next_extent(), 0);
1159 assert_eq!(block.reference_count(), 0);
1160 assert_eq!(block.total_length(), 0);
1161 assert_eq!(block.inline_data().unwrap(), Vec::<u8>::new());
1162 assert_8_bytes!(container, 0, [0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1163 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1164 }
1165
1166 #[fuchsia::test]
1167 fn test_inline_string_reference() {
1168 let (mut container, _storage) =
1169 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1170 let mut block = get_reserved(&mut container);
1171 block.set_order(0).unwrap();
1172 let mut block = block.become_string_reference();
1173
1174 assert_eq!(block.write_inline("ab".as_bytes()), 2);
1175 assert_eq!(block.reference_count(), 0);
1176 assert_eq!(block.total_length(), 2);
1177 assert_eq!(block.order(), 0);
1178 assert_eq!(*block.next_extent(), 0);
1179 assert_eq!(block.inline_data().unwrap(), "ab".as_bytes());
1180
1181 assert_eq!(block.write_inline("abcd".as_bytes()), 4);
1182 assert_eq!(block.reference_count(), 0);
1183 assert_eq!(block.total_length(), 4);
1184 assert_eq!(block.order(), 0);
1185 assert_eq!(*block.next_extent(), 0);
1186 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1187
1188 assert_eq!(
1189 block.write_inline("abcdefghijklmnopqrstuvwxyz".as_bytes()),
1190 4 );
1192 assert_eq!(block.reference_count(), 0);
1193 assert_eq!(block.total_length(), 26);
1194 assert_eq!(block.order(), 0);
1195 assert_eq!(*block.next_extent(), 0);
1196 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1197
1198 assert_eq!(block.write_inline("abcdef".as_bytes()), 4);
1199 assert_eq!(block.reference_count(), 0);
1200 assert_eq!(block.total_length(), 6);
1201 assert_eq!(block.order(), 0);
1202 assert_eq!(*block.next_extent(), 0);
1203 assert_eq!(block.inline_data().unwrap(), "abcd".as_bytes());
1204 }
1205
1206 #[fuchsia::test]
1207 fn test_string_reference_count() {
1208 let (mut container, _storage) =
1209 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1210 let mut block = get_reserved(&mut container);
1211 block.set_order(0).unwrap();
1212 let mut block = block.become_string_reference();
1213 assert_eq!(block.reference_count(), 0);
1214
1215 assert!(block.increment_ref_count().is_ok());
1216 assert_eq!(block.reference_count(), 1);
1217
1218 assert!(block.decrement_ref_count().is_ok());
1219 assert_eq!(block.reference_count(), 0);
1220
1221 assert!(block.decrement_ref_count().is_err());
1222 assert_eq!(block.reference_count(), 0);
1223 }
1224
1225 #[fuchsia::test]
1226 fn test_become_header() {
1227 let (mut container, _storage) =
1228 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1229 let block =
1230 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1231 assert_eq!(block.block_type(), Some(BlockType::Header));
1232 assert_eq!(*block.index(), 0);
1233 assert_eq!(block.order(), constants::HEADER_ORDER);
1234 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1235 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1236 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::MIN_ORDER_SIZE * 2);
1237 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1238 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1239 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1240 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1241 }
1242
1243 #[fuchsia::test]
1244 fn test_header_without_size() {
1245 let (mut container, _storage) =
1246 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1247 let block =
1248 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1249 assert_eq!(block.order(), constants::HEADER_ORDER);
1250 assert!(block.vmo_size().unwrap().is_some());
1251
1252 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1253
1254 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1256 assert!(block.set_order(0).is_ok());
1257 assert_eq!(block.vmo_size().unwrap(), None);
1258 assert!(block.set_vmo_size(123456789).is_ok());
1260 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1261 }
1262
1263 #[fuchsia::test]
1264 fn test_freeze_thaw_header() {
1265 let (mut container, _storage) =
1266 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1267 let block =
1268 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1269 assert_eq!(block.block_type(), Some(BlockType::Header));
1270 assert_eq!(*block.index(), 0);
1271 assert_eq!(block.order(), constants::HEADER_ORDER);
1272 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1273 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1274 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1275 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1276 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1277 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1278
1279 let old = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).freeze();
1280 assert_8_bytes!(container, 8, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1281 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1282 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1283 container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).thaw(old);
1284 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1285 assert_8_bytes!(container, 16, [0x020, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1286 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1287 }
1288
1289 #[fuchsia::test]
1290 #[should_panic]
1291 fn test_cant_unlock_locked_header() {
1292 let (mut container, _storage) =
1293 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1294 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1295 block.unlock();
1297 }
1298
1299 #[fuchsia::test]
1300 #[should_panic]
1301 fn test_cant_lock_locked_header() {
1302 let (mut container, _storage) =
1303 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1304 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1305 block.lock();
1306 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1308 block.lock();
1309 }
1310
1311 #[fuchsia::test]
1312 #[should_panic]
1313 fn test_header_overflow() {
1314 let (mut container, _storage) =
1317 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1318 container.set_value(8, u64::MAX);
1319 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1320 block.lock();
1321 }
1322
1323 #[fuchsia::test]
1324 fn test_lock_unlock_header() {
1325 let (mut container, _storage) =
1326 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1327 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1328 block.lock();
1329 assert!(block.is_locked());
1330 assert_eq!(block.generation_count(), 1);
1331 let header_bytes: [u8; 8] = [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50];
1332 assert_8_bytes!(container, 0, header_bytes[..]);
1333 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1334 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1335 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1336 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1337 block.unlock();
1338 assert!(!block.is_locked());
1339 assert_eq!(block.generation_count(), 2);
1340 assert_8_bytes!(container, 0, header_bytes[..]);
1341 assert_8_bytes!(container, 8, [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1342 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1343 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1344
1345 container.set_value(8, u64::MAX);
1347 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1348 block.unlock();
1349 assert_eq!(block.generation_count(), 0);
1350 assert_8_bytes!(container, 0, header_bytes[..]);
1351 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1352 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1353 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1354 }
1355
1356 #[fuchsia::test]
1357 fn test_header_vmo_size() {
1358 let (mut container, _storage) =
1359 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1360 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1361 assert!(block.set_vmo_size(constants::DEFAULT_VMO_SIZE_BYTES.try_into().unwrap()).is_ok());
1362 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1363 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1364 assert_8_bytes!(container, 16, [0x00, 0x00, 0x4, 0x00, 0x00, 0x00, 0x00, 0x00]);
1365 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1366 let block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1367 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::DEFAULT_VMO_SIZE_BYTES);
1368 }
1369
1370 #[fuchsia::test]
1371 fn test_become_tombstone() {
1372 let (mut container, _storage) =
1373 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1374 let mut block = get_reserved(&mut container).become_node(2.into(), 3.into());
1375 block.set_child_count(4);
1376 let block = block.become_tombstone();
1377 assert_eq!(block.block_type(), Some(BlockType::Tombstone));
1378 assert_eq!(block.child_count(), 4);
1379 assert_8_bytes!(container, 0, [0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1380 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1381 }
1382
1383 #[fuchsia::test]
1384 fn test_child_count() {
1385 let (mut container, _storage) =
1386 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1387 let _ = get_reserved(&mut container).become_node(2.into(), 3.into());
1388 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1389 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1390 let mut block = container.block_at_unchecked_mut::<Node>(BlockIndex::EMPTY);
1391 block.set_child_count(4);
1392 assert_eq!(block.child_count(), 4);
1393 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1394 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1395 }
1396
1397 #[fuchsia::test]
1398 fn test_free() {
1399 let (mut container, _storage) =
1400 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1401 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1402 block.set_free_next_index(3.into());
1403 assert_eq!(*block.free_next_index(), 3);
1404 assert_8_bytes!(container, 0, [0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1405 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1406 }
1407
1408 #[fuchsia::test]
1409 fn test_extent() {
1410 let (mut container, _storage) =
1411 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1412 let block = get_reserved(&mut container).become_extent(3.into());
1413 assert_eq!(block.block_type(), Some(BlockType::Extent));
1414 assert_eq!(*block.next_extent(), 3);
1415 assert_8_bytes!(container, 0, [0x01, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1416 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1417
1418 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1419 assert_eq!(block.set_contents("test-rust-inspect".as_bytes()), 17);
1420 assert_eq!(
1421 String::from_utf8(block.contents().unwrap().to_vec()).unwrap(),
1422 "test-rust-inspect\0\0\0\0\0\0\0"
1423 );
1424 let slice = container.get_slice_at(8, 17).unwrap();
1425 assert_eq!(slice, "test-rust-inspect".as_bytes());
1426 let slice = container.get_slice_at(25, 7).unwrap();
1427 assert_eq!(slice, &[0, 0, 0, 0, 0, 0, 0]);
1428
1429 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1430 block.set_next_index(4.into());
1431 assert_eq!(*block.next_extent(), 4);
1432 }
1433
1434 #[fuchsia::test]
1435 fn test_double_value() {
1436 let (mut container, _storage) =
1437 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1438 let block = get_reserved(&mut container).become_double_value(1.0, 2.into(), 3.into());
1439 assert_eq!(block.block_type(), Some(BlockType::DoubleValue));
1440 assert_eq!(*block.name_index(), 2);
1441 assert_eq!(*block.parent_index(), 3);
1442 assert_eq!(block.value(), 1.0);
1443 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1444 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f]);
1445
1446 let mut block = container.block_at_unchecked_mut::<Double>(BlockIndex::EMPTY);
1447 block.set(5.0);
1448 assert_eq!(block.value(), 5.0);
1449 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1450 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40]);
1451 }
1452
1453 #[fuchsia::test]
1454 fn test_int_value() {
1455 let (mut container, _storage) =
1456 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1457 let block = get_reserved(&mut container).become_int_value(1, 2.into(), 3.into());
1458 assert_eq!(block.block_type(), Some(BlockType::IntValue));
1459 assert_eq!(*block.name_index(), 2);
1460 assert_eq!(*block.parent_index(), 3);
1461 assert_eq!(block.value(), 1);
1462 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1463 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1464
1465 let mut block = container.block_at_unchecked_mut::<Int>(BlockIndex::EMPTY);
1466 block.set(-5);
1467 assert_eq!(block.value(), -5);
1468 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1469 assert_8_bytes!(container, 8, [0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
1470 }
1471
1472 #[fuchsia::test]
1473 fn test_uint_value() {
1474 let (mut container, _storage) =
1475 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1476 let block = get_reserved(&mut container).become_uint_value(1, 2.into(), 3.into());
1477 assert_eq!(block.block_type(), Some(BlockType::UintValue));
1478 assert_eq!(*block.name_index(), 2);
1479 assert_eq!(*block.parent_index(), 3);
1480 assert_eq!(block.value(), 1);
1481 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1482 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1483
1484 let mut block = container.block_at_unchecked_mut::<Uint>(BlockIndex::EMPTY);
1485 block.set(5);
1486 assert_eq!(block.value(), 5);
1487 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1488 assert_8_bytes!(container, 8, [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1489 }
1490
1491 #[fuchsia::test]
1492 fn test_bool_value() {
1493 let (mut container, _storage) =
1494 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1495 let block = get_reserved(&mut container).become_bool_value(false, 2.into(), 3.into());
1496 assert_eq!(block.block_type(), Some(BlockType::BoolValue));
1497 assert_eq!(*block.name_index(), 2);
1498 assert_eq!(*block.parent_index(), 3);
1499 assert!(!block.value());
1500 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1501 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1502
1503 let mut block = container.block_at_unchecked_mut::<Bool>(BlockIndex::EMPTY);
1504 block.set(true);
1505 assert!(block.value());
1506 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1507 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1508 }
1509
1510 #[fuchsia::test]
1511 fn test_become_node() {
1512 let (mut container, _storage) =
1513 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1514 let block = get_reserved(&mut container).become_node(2.into(), 3.into());
1515 assert_eq!(block.block_type(), Some(BlockType::NodeValue));
1516 assert_eq!(*block.name_index(), 2);
1517 assert_eq!(*block.parent_index(), 3);
1518 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1519 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1520 }
1521
1522 #[fuchsia::test]
1523 fn test_property() {
1524 let (mut container, _storage) =
1525 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1526 let block =
1527 get_reserved(&mut container).become_property(2.into(), 3.into(), PropertyFormat::Bytes);
1528 assert_eq!(block.block_type(), Some(BlockType::BufferValue));
1529 assert_eq!(*block.name_index(), 2);
1530 assert_eq!(*block.parent_index(), 3);
1531 assert_eq!(block.format(), Some(PropertyFormat::Bytes));
1532 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1533 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1534
1535 let (mut bad_container, _storage) =
1536 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1537 let mut bad_format_bytes = [0u8; constants::MIN_ORDER_SIZE];
1538 bad_format_bytes[15] = 0x30;
1539 bad_container.copy_from_slice(&bad_format_bytes);
1540 let bad_block = Block::<_, Buffer>::new(&bad_container, BlockIndex::EMPTY);
1541 assert_eq!(bad_block.format(), None);
1542
1543 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1544 block.set_extent_index(4.into());
1545 assert_eq!(*block.extent_index(), 4);
1546 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1547 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1548
1549 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1550 block.set_total_length(10);
1551 assert_eq!(block.total_length(), 10);
1552 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1553 assert_8_bytes!(container, 8, [0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1554 }
1555
1556 #[fuchsia::test]
1557 fn test_name() {
1558 let (mut container, _storage) =
1559 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1560 let block = get_reserved(&mut container).become_name("test-rust-inspect");
1561 assert_eq!(block.block_type(), Some(BlockType::Name));
1562 assert_eq!(block.length(), 17);
1563 assert_eq!(block.contents().unwrap(), "test-rust-inspect");
1564 assert_8_bytes!(container, 0, [0x01, 0x09, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
1565 let slice = container.get_slice_at(8, 17).unwrap();
1566 assert_eq!(slice, "test-rust-inspect".as_bytes());
1567 let slice = container.get_slice_at(25, 7).unwrap();
1568 assert_eq!(slice, [0, 0, 0, 0, 0, 0, 0]);
1569
1570 *container.get_value_mut::<u8>(24).unwrap() = 0xff;
1571 let bad_block = Block::<_, Name>::new(&container, BlockIndex::EMPTY);
1572 assert_eq!(bad_block.length(), 17); assert!(bad_block.contents().is_err()); let (mut container, _storage) =
1578 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1579 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstuvwxyz");
1580 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstuvwx");
1581
1582 let (mut container, _storage) =
1583 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1584 let block = get_reserved(&mut container).become_name("😀abcdefghijklmnopqrstuvwxyz");
1585 assert_eq!(block.contents().unwrap(), "😀abcdefghijklmnopqrst");
1586
1587 let (mut container, _storage) =
1588 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1589 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstu😀");
1590 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstu");
1591 let byte = container.get_value::<u8>(31).unwrap();
1592 assert_eq!(*byte, 0);
1593 }
1594
1595 #[fuchsia::test]
1596 fn test_invalid_type_for_array() {
1597 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1598 container.get_slice_mut_at(24, 2048 - 24).unwrap().fill(14);
1599
1600 fn become_array<S: ArraySlotKind>(
1601 container: &mut Container,
1602 format: ArrayFormat,
1603 ) -> Result<Block<&mut Container, Array<S>>, Error> {
1604 get_reserved_of_order(container, 4).become_array_value::<S>(
1605 4,
1606 format,
1607 BlockIndex::EMPTY,
1608 BlockIndex::EMPTY,
1609 )
1610 }
1611
1612 assert!(become_array::<Int>(&mut container, ArrayFormat::Default).is_ok());
1613 assert!(become_array::<Uint>(&mut container, ArrayFormat::Default).is_ok());
1614 assert!(become_array::<Double>(&mut container, ArrayFormat::Default).is_ok());
1615 assert!(become_array::<StringRef>(&mut container, ArrayFormat::Default).is_ok());
1616
1617 for format in [ArrayFormat::LinearHistogram, ArrayFormat::ExponentialHistogram] {
1618 assert!(become_array::<Int>(&mut container, format).is_ok());
1619 assert!(become_array::<Uint>(&mut container, format).is_ok());
1620 assert!(become_array::<Double>(&mut container, format).is_ok());
1621 assert!(become_array::<StringRef>(&mut container, format).is_err());
1622 }
1623 }
1624
1625 #[fuchsia::test]
1631 fn test_string_arrays() {
1632 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1633 container.get_slice_mut_at(48, 2048 - 48).unwrap().fill(14);
1634
1635 let parent_index = BlockIndex::new(0);
1636 let name_index = BlockIndex::new(1);
1637 let mut block = get_reserved(&mut container)
1638 .become_array_value::<StringRef>(4, ArrayFormat::Default, name_index, parent_index)
1639 .unwrap();
1640
1641 for i in 0..4 {
1642 block.set_string_slot(i, ((i + 4) as u32).into());
1643 }
1644
1645 for i in 0..4 {
1646 let read_index = block.get_string_index_at(i).unwrap();
1647 assert_eq!(*read_index, (i + 4) as u32);
1648 }
1649
1650 assert_8_bytes!(
1651 container,
1652 0,
1653 [
1654 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
1657 ]
1658 );
1659 assert_8_bytes!(container, 8, [0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1660 for i in 0..4 {
1661 let slice = container.get_slice_at(16 + (i * 4), 4).unwrap();
1662 assert_eq!(slice, [(i as u8 + 4), 0x00, 0x00, 0x00]);
1663 }
1664 }
1665
1666 #[fuchsia::test]
1667 fn become_array() {
1668 let (mut container, _storage) = Container::read_and_write(128).unwrap();
1670 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1671
1672 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1673 .unwrap()
1674 .become_reserved()
1675 .become_array_value::<Int>(
1676 14,
1677 ArrayFormat::Default,
1678 BlockIndex::EMPTY,
1679 BlockIndex::EMPTY,
1680 )
1681 .unwrap();
1682 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1683 slice
1684 .iter()
1685 .enumerate()
1686 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1687
1688 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1689 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1690 .unwrap()
1691 .become_reserved()
1692 .become_array_value::<Int>(
1693 14,
1694 ArrayFormat::LinearHistogram,
1695 BlockIndex::EMPTY,
1696 BlockIndex::EMPTY,
1697 )
1698 .unwrap();
1699 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1700 slice
1701 .iter()
1702 .enumerate()
1703 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1704
1705 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1706 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1707 .unwrap()
1708 .become_reserved()
1709 .become_array_value::<Int>(
1710 14,
1711 ArrayFormat::ExponentialHistogram,
1712 BlockIndex::EMPTY,
1713 BlockIndex::EMPTY,
1714 )
1715 .unwrap();
1716 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1717 slice
1718 .iter()
1719 .enumerate()
1720 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1721
1722 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1723 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1724 .unwrap()
1725 .become_reserved()
1726 .become_array_value::<StringRef>(
1727 28,
1728 ArrayFormat::Default,
1729 BlockIndex::EMPTY,
1730 BlockIndex::EMPTY,
1731 )
1732 .unwrap();
1733 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1734 slice
1735 .iter()
1736 .enumerate()
1737 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1738 }
1739
1740 #[fuchsia::test]
1741 fn uint_array_value() {
1742 let (mut container, _storage) =
1743 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1744 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1745 .unwrap()
1746 .become_reserved()
1747 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1748 .unwrap();
1749
1750 assert_eq!(block.block_type(), Some(BlockType::ArrayValue));
1751 assert_eq!(*block.parent_index(), 2);
1752 assert_eq!(*block.name_index(), 3);
1753 assert_eq!(block.format(), Some(ArrayFormat::LinearHistogram));
1754 assert_eq!(block.slots(), 4);
1755 assert_eq!(block.entry_type(), Some(BlockType::UintValue));
1756
1757 for i in 0..4 {
1758 block.set(i, (i as u64 + 1) * 5);
1759 }
1760 block.set(4, 3);
1761 block.set(7, 5);
1762
1763 assert_8_bytes!(container, 0, [0x02, 0x0b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00]);
1764 assert_8_bytes!(container, 8, [0x15, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1765 for i in 0..4 {
1766 assert_8_bytes!(
1767 container,
1768 8 * (i + 2),
1769 [(i as u8 + 1) * 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1770 );
1771 }
1772
1773 let (mut bad_container, _storage) =
1774 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1775 let mut bad_bytes = [0u8; constants::MIN_ORDER_SIZE];
1776 container.copy_bytes(&mut bad_bytes[..]);
1777 bad_bytes[8] = 0x12; bad_container.copy_from_slice(&bad_bytes);
1779 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1780 assert_eq!(bad_block.format(), Some(ArrayFormat::LinearHistogram));
1781 assert_eq!(bad_block.entry_type(), None);
1783
1784 bad_bytes[8] = 0xef; bad_container.copy_from_slice(&bad_bytes);
1786 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1787 assert_eq!(bad_block.format(), None);
1788 assert_eq!(bad_block.entry_type(), None);
1789
1790 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1791 for i in 0..4 {
1792 assert_eq!(block.get(i), Some((i as u64 + 1) * 5));
1793 }
1794 assert_eq!(block.get(4), None);
1795 }
1796
1797 #[fuchsia::test]
1798 fn array_slots_bigger_than_block_order() {
1799 let (mut container, _storage) =
1800 Container::read_and_write(constants::MAX_ORDER_SIZE).unwrap();
1801 assert!(Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1804 .unwrap()
1805 .become_reserved()
1806 .become_array_value::<Int>(257, ArrayFormat::Default, 1.into(), 2.into())
1807 .is_err());
1808 assert!(Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1809 .unwrap()
1810 .become_reserved()
1811 .become_array_value::<Int>(254, ArrayFormat::Default, 1.into(), 2.into())
1812 .is_ok());
1813
1814 assert!(Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1817 .unwrap()
1818 .become_reserved()
1819 .become_array_value::<Int>(8, ArrayFormat::Default, 1.into(), 2.into())
1820 .is_err());
1821 assert!(Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1822 .unwrap()
1823 .become_reserved()
1824 .become_array_value::<Int>(6, ArrayFormat::Default, 1.into(), 2.into())
1825 .is_ok());
1826 }
1827
1828 #[fuchsia::test]
1829 fn array_clear() {
1830 let (mut container, _storage) =
1831 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1832
1833 let sample = [0xff, 0xff, 0xff];
1835 container.copy_from_slice_at(48, &sample);
1836
1837 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1838 .unwrap()
1839 .become_reserved()
1840 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1841 .unwrap();
1842
1843 for i in 0..4 {
1844 block.set(i, (i + 1) as u64);
1845 }
1846
1847 block.clear(1);
1848
1849 assert_eq!(1, block.get(0).expect("get uint 0"));
1850 assert_8_bytes!(container, 16, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1851
1852 for i in 1..4 {
1853 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1854 assert_eq!(0, block.get(i).expect("get uint"));
1855 assert_8_bytes!(
1856 container,
1857 16 + (i * 8),
1858 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1859 );
1860 }
1861
1862 let slice = container.get_slice_at(48, 3).unwrap();
1864 assert_eq!(slice, &sample[..]);
1865 }
1866
1867 #[fuchsia::test]
1868 fn become_link() {
1869 let (mut container, _storage) =
1870 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1871 let block = get_reserved(&mut container).become_link(
1872 BlockIndex::new(1),
1873 BlockIndex::new(2),
1874 BlockIndex::new(3),
1875 LinkNodeDisposition::Inline,
1876 );
1877 assert_eq!(*block.name_index(), 1);
1878 assert_eq!(*block.parent_index(), 2);
1879 assert_eq!(*block.content_index(), 3);
1880 assert_eq!(block.block_type(), Some(BlockType::LinkValue));
1881 assert_eq!(block.link_node_disposition(), Some(LinkNodeDisposition::Inline));
1882 assert_8_bytes!(container, 0, [0x01, 0x0c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00]);
1883 assert_8_bytes!(container, 8, [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1884 }
1885
1886 #[test]
1887 fn array_capacity_numeric() {
1888 assert_eq!(2, max_array_capacity::<Int>(1));
1889 assert_eq!(2 + 4, max_array_capacity::<Int>(2));
1890 assert_eq!(2 + 4 + 8, max_array_capacity::<Int>(3));
1891 assert_eq!(2 + 4 + 8 + 16, max_array_capacity::<Int>(4));
1892 assert_eq!(2 + 4 + 8 + 16 + 32, max_array_capacity::<Int>(5));
1893 assert_eq!(2 + 4 + 8 + 16 + 32 + 64, max_array_capacity::<Int>(6));
1894 assert_eq!(2 + 4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<Int>(7),);
1895 }
1896
1897 #[test]
1898 fn array_capacity_string_reference() {
1899 assert_eq!(4, max_array_capacity::<StringRef>(1));
1900 assert_eq!(4 + 8, max_array_capacity::<StringRef>(2));
1901 assert_eq!(4 + 8 + 16, max_array_capacity::<StringRef>(3));
1902 assert_eq!(4 + 8 + 16 + 32, max_array_capacity::<StringRef>(4));
1903 assert_eq!(4 + 8 + 16 + 32 + 64, max_array_capacity::<StringRef>(5));
1904 assert_eq!(4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<StringRef>(6));
1905 assert_eq!(4 + 8 + 16 + 32 + 64 + 128 + 256, max_array_capacity::<StringRef>(7));
1906 }
1907
1908 fn get_header(container: &mut Container, size: usize) -> Block<&mut Container, Header> {
1909 get_reserved(container).become_header(size).unwrap()
1910 }
1911
1912 fn get_reserved(container: &mut Container) -> Block<&mut Container, Reserved> {
1913 get_reserved_of_order(container, 1)
1914 }
1915
1916 fn get_reserved_of_order(
1917 container: &mut Container,
1918 order: u8,
1919 ) -> Block<&mut Container, Reserved> {
1920 let block = Block::free(container, BlockIndex::EMPTY, order, BlockIndex::new(0)).unwrap();
1921 block.become_reserved()
1922 }
1923}