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 return Err(Error::InvalidReferenceCount);
985 }
986 let new_count = cur + 1;
987 HeaderFields::set_string_reference_count(self, new_count);
988 Ok(())
989 }
990
991 pub fn decrement_ref_count(&mut self) -> Result<(), Error> {
993 let cur = HeaderFields::string_reference_count(self);
994 let new_count = cur.checked_sub(1).ok_or(Error::InvalidReferenceCount)?;
995 HeaderFields::set_string_reference_count(self, new_count);
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
1228 #[fuchsia::test]
1229 fn test_become_header() {
1230 let (mut container, _storage) =
1231 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1232 let block =
1233 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1234 assert_eq!(block.block_type(), Some(BlockType::Header));
1235 assert_eq!(*block.index(), 0);
1236 assert_eq!(block.order(), constants::HEADER_ORDER);
1237 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1238 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1239 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::MIN_ORDER_SIZE * 2);
1240 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1241 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1242 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1243 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1244 }
1245
1246 #[fuchsia::test]
1247 fn test_header_without_size() {
1248 let (mut container, _storage) =
1249 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1250 let block =
1251 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1252 assert_eq!(block.order(), constants::HEADER_ORDER);
1253 assert!(block.vmo_size().unwrap().is_some());
1254
1255 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1256
1257 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1259 assert!(block.set_order(0).is_ok());
1260 assert_eq!(block.vmo_size().unwrap(), None);
1261 assert!(block.set_vmo_size(123456789).is_ok());
1263 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1264 }
1265
1266 #[fuchsia::test]
1267 fn test_freeze_thaw_header() {
1268 let (mut container, _storage) =
1269 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1270 let block =
1271 get_reserved(&mut container).become_header(constants::MIN_ORDER_SIZE * 2).unwrap();
1272 assert_eq!(block.block_type(), Some(BlockType::Header));
1273 assert_eq!(*block.index(), 0);
1274 assert_eq!(block.order(), constants::HEADER_ORDER);
1275 assert_eq!(block.magic_number(), constants::HEADER_MAGIC_NUMBER);
1276 assert_eq!(block.version(), constants::HEADER_VERSION_NUMBER);
1277 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1278 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1279 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1280 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1281
1282 let old = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).freeze();
1283 assert_8_bytes!(container, 8, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1284 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1285 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1286 container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER).thaw(old);
1287 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1288 assert_8_bytes!(container, 16, [0x020, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1289 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1290 }
1291
1292 #[fuchsia::test]
1293 #[should_panic]
1294 fn test_cant_unlock_locked_header() {
1295 let (mut container, _storage) =
1296 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1297 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1298 block.unlock();
1300 }
1301
1302 #[fuchsia::test]
1303 #[should_panic]
1304 fn test_cant_lock_locked_header() {
1305 let (mut container, _storage) =
1306 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1307 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1308 block.lock();
1309 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1311 block.lock();
1312 }
1313
1314 #[fuchsia::test]
1315 #[should_panic]
1316 fn test_header_overflow() {
1317 let (mut container, _storage) =
1320 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1321 container.set_value(8, u64::MAX);
1322 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1323 block.lock();
1324 }
1325
1326 #[fuchsia::test]
1327 fn test_lock_unlock_header() {
1328 let (mut container, _storage) =
1329 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1330 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1331 block.lock();
1332 assert!(block.is_locked());
1333 assert_eq!(block.generation_count(), 1);
1334 let header_bytes: [u8; 8] = [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50];
1335 assert_8_bytes!(container, 0, header_bytes[..]);
1336 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1337 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1338 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1339 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1340 block.unlock();
1341 assert!(!block.is_locked());
1342 assert_eq!(block.generation_count(), 2);
1343 assert_8_bytes!(container, 0, header_bytes[..]);
1344 assert_8_bytes!(container, 8, [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1345 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1346 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1347
1348 container.set_value(8, u64::MAX);
1350 let mut block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1351 block.unlock();
1352 assert_eq!(block.generation_count(), 0);
1353 assert_8_bytes!(container, 0, header_bytes[..]);
1354 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1355 assert_8_bytes!(container, 16, [0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1356 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1357 }
1358
1359 #[fuchsia::test]
1360 fn test_header_vmo_size() {
1361 let (mut container, _storage) =
1362 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1363 let mut block = get_header(&mut container, constants::MIN_ORDER_SIZE * 2);
1364 assert!(block.set_vmo_size(constants::DEFAULT_VMO_SIZE_BYTES.try_into().unwrap()).is_ok());
1365 assert_8_bytes!(container, 0, [0x01, 0x02, 0x02, 0x00, 0x49, 0x4e, 0x53, 0x50]);
1366 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1367 assert_8_bytes!(container, 16, [0x00, 0x00, 0x4, 0x00, 0x00, 0x00, 0x00, 0x00]);
1368 assert_8_bytes!(container, 24, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1369 let block = container.block_at_unchecked_mut::<Header>(BlockIndex::HEADER);
1370 assert_eq!(block.vmo_size().unwrap().unwrap() as usize, constants::DEFAULT_VMO_SIZE_BYTES);
1371 }
1372
1373 #[fuchsia::test]
1374 fn test_become_tombstone() {
1375 let (mut container, _storage) =
1376 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1377 let mut block = get_reserved(&mut container).become_node(2.into(), 3.into());
1378 block.set_child_count(4);
1379 let block = block.become_tombstone();
1380 assert_eq!(block.block_type(), Some(BlockType::Tombstone));
1381 assert_eq!(block.child_count(), 4);
1382 assert_8_bytes!(container, 0, [0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1383 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1384 }
1385
1386 #[fuchsia::test]
1387 fn test_child_count() {
1388 let (mut container, _storage) =
1389 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1390 let _ = get_reserved(&mut container).become_node(2.into(), 3.into());
1391 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1392 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1393 let mut block = container.block_at_unchecked_mut::<Node>(BlockIndex::EMPTY);
1394 block.set_child_count(4);
1395 assert_eq!(block.child_count(), 4);
1396 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1397 assert_8_bytes!(container, 8, [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1398 }
1399
1400 #[fuchsia::test]
1401 fn test_free() {
1402 let (mut container, _storage) =
1403 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1404 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 1, 1.into()).unwrap();
1405 block.set_free_next_index(3.into());
1406 assert_eq!(*block.free_next_index(), 3);
1407 assert_8_bytes!(container, 0, [0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1408 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1409 }
1410
1411 #[fuchsia::test]
1412 fn test_extent() {
1413 let (mut container, _storage) =
1414 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1415 let block = get_reserved(&mut container).become_extent(3.into());
1416 assert_eq!(block.block_type(), Some(BlockType::Extent));
1417 assert_eq!(*block.next_extent(), 3);
1418 assert_8_bytes!(container, 0, [0x01, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]);
1419 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1420
1421 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1422 assert_eq!(block.set_contents("test-rust-inspect".as_bytes()), 17);
1423 assert_eq!(
1424 String::from_utf8(block.contents().unwrap().to_vec()).unwrap(),
1425 "test-rust-inspect\0\0\0\0\0\0\0"
1426 );
1427 let slice = container.get_slice_at(8, 17).unwrap();
1428 assert_eq!(slice, "test-rust-inspect".as_bytes());
1429 let slice = container.get_slice_at(25, 7).unwrap();
1430 assert_eq!(slice, &[0, 0, 0, 0, 0, 0, 0]);
1431
1432 let mut block = container.block_at_unchecked_mut::<Extent>(BlockIndex::EMPTY);
1433 block.set_next_index(4.into());
1434 assert_eq!(*block.next_extent(), 4);
1435 }
1436
1437 #[fuchsia::test]
1438 fn test_double_value() {
1439 let (mut container, _storage) =
1440 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1441 let block = get_reserved(&mut container).become_double_value(1.0, 2.into(), 3.into());
1442 assert_eq!(block.block_type(), Some(BlockType::DoubleValue));
1443 assert_eq!(*block.name_index(), 2);
1444 assert_eq!(*block.parent_index(), 3);
1445 assert_eq!(block.value(), 1.0);
1446 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1447 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f]);
1448
1449 let mut block = container.block_at_unchecked_mut::<Double>(BlockIndex::EMPTY);
1450 block.set(5.0);
1451 assert_eq!(block.value(), 5.0);
1452 assert_8_bytes!(container, 0, [0x01, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1453 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40]);
1454 }
1455
1456 #[fuchsia::test]
1457 fn test_int_value() {
1458 let (mut container, _storage) =
1459 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1460 let block = get_reserved(&mut container).become_int_value(1, 2.into(), 3.into());
1461 assert_eq!(block.block_type(), Some(BlockType::IntValue));
1462 assert_eq!(*block.name_index(), 2);
1463 assert_eq!(*block.parent_index(), 3);
1464 assert_eq!(block.value(), 1);
1465 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1466 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1467
1468 let mut block = container.block_at_unchecked_mut::<Int>(BlockIndex::EMPTY);
1469 block.set(-5);
1470 assert_eq!(block.value(), -5);
1471 assert_8_bytes!(container, 0, [0x1, 0x04, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1472 assert_8_bytes!(container, 8, [0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
1473 }
1474
1475 #[fuchsia::test]
1476 fn test_uint_value() {
1477 let (mut container, _storage) =
1478 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1479 let block = get_reserved(&mut container).become_uint_value(1, 2.into(), 3.into());
1480 assert_eq!(block.block_type(), Some(BlockType::UintValue));
1481 assert_eq!(*block.name_index(), 2);
1482 assert_eq!(*block.parent_index(), 3);
1483 assert_eq!(block.value(), 1);
1484 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1485 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1486
1487 let mut block = container.block_at_unchecked_mut::<Uint>(BlockIndex::EMPTY);
1488 block.set(5);
1489 assert_eq!(block.value(), 5);
1490 assert_8_bytes!(container, 0, [0x01, 0x05, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1491 assert_8_bytes!(container, 8, [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1492 }
1493
1494 #[fuchsia::test]
1495 fn test_bool_value() {
1496 let (mut container, _storage) =
1497 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1498 let block = get_reserved(&mut container).become_bool_value(false, 2.into(), 3.into());
1499 assert_eq!(block.block_type(), Some(BlockType::BoolValue));
1500 assert_eq!(*block.name_index(), 2);
1501 assert_eq!(*block.parent_index(), 3);
1502 assert!(!block.value());
1503 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1504 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1505
1506 let mut block = container.block_at_unchecked_mut::<Bool>(BlockIndex::EMPTY);
1507 block.set(true);
1508 assert!(block.value());
1509 assert_8_bytes!(container, 0, [0x01, 0x0D, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1510 assert_8_bytes!(container, 8, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1511 }
1512
1513 #[fuchsia::test]
1514 fn test_become_node() {
1515 let (mut container, _storage) =
1516 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1517 let block = get_reserved(&mut container).become_node(2.into(), 3.into());
1518 assert_eq!(block.block_type(), Some(BlockType::NodeValue));
1519 assert_eq!(*block.name_index(), 2);
1520 assert_eq!(*block.parent_index(), 3);
1521 assert_8_bytes!(container, 0, [0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1522 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1523 }
1524
1525 #[fuchsia::test]
1526 fn test_property() {
1527 let (mut container, _storage) =
1528 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1529 let block =
1530 get_reserved(&mut container).become_property(2.into(), 3.into(), PropertyFormat::Bytes);
1531 assert_eq!(block.block_type(), Some(BlockType::BufferValue));
1532 assert_eq!(*block.name_index(), 2);
1533 assert_eq!(*block.parent_index(), 3);
1534 assert_eq!(block.format(), Some(PropertyFormat::Bytes));
1535 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1536 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1537
1538 let (mut bad_container, _storage) =
1539 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1540 let mut bad_format_bytes = [0u8; constants::MIN_ORDER_SIZE];
1541 bad_format_bytes[15] = 0x30;
1542 bad_container.copy_from_slice(&bad_format_bytes);
1543 let bad_block = Block::<_, Buffer>::new(&bad_container, BlockIndex::EMPTY);
1544 assert_eq!(bad_block.format(), None);
1545
1546 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1547 block.set_extent_index(4.into());
1548 assert_eq!(*block.extent_index(), 4);
1549 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1550 assert_8_bytes!(container, 8, [0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1551
1552 let mut block = container.block_at_unchecked_mut::<Buffer>(BlockIndex::EMPTY);
1553 block.set_total_length(10);
1554 assert_eq!(block.total_length(), 10);
1555 assert_8_bytes!(container, 0, [0x01, 0x07, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00]);
1556 assert_8_bytes!(container, 8, [0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10]);
1557 }
1558
1559 #[fuchsia::test]
1560 fn test_name() {
1561 let (mut container, _storage) =
1562 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1563 let block = get_reserved(&mut container).become_name("test-rust-inspect");
1564 assert_eq!(block.block_type(), Some(BlockType::Name));
1565 assert_eq!(block.length(), 17);
1566 assert_eq!(block.contents().unwrap(), "test-rust-inspect");
1567 assert_8_bytes!(container, 0, [0x01, 0x09, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
1568 let slice = container.get_slice_at(8, 17).unwrap();
1569 assert_eq!(slice, "test-rust-inspect".as_bytes());
1570 let slice = container.get_slice_at(25, 7).unwrap();
1571 assert_eq!(slice, [0, 0, 0, 0, 0, 0, 0]);
1572
1573 *container.get_value_mut::<u8>(24).unwrap() = 0xff;
1574 let bad_block = Block::<_, Name>::new(&container, BlockIndex::EMPTY);
1575 assert_eq!(bad_block.length(), 17); assert!(bad_block.contents().is_err()); let (mut container, _storage) =
1581 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1582 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstuvwxyz");
1583 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstuvwx");
1584
1585 let (mut container, _storage) =
1586 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1587 let block = get_reserved(&mut container).become_name("😀abcdefghijklmnopqrstuvwxyz");
1588 assert_eq!(block.contents().unwrap(), "😀abcdefghijklmnopqrst");
1589
1590 let (mut container, _storage) =
1591 Container::read_and_write(constants::MIN_ORDER_SIZE * 2).unwrap();
1592 let block = get_reserved(&mut container).become_name("abcdefghijklmnopqrstu😀");
1593 assert_eq!(block.contents().unwrap(), "abcdefghijklmnopqrstu");
1594 let byte = container.get_value::<u8>(31).unwrap();
1595 assert_eq!(*byte, 0);
1596 }
1597
1598 #[fuchsia::test]
1599 fn test_invalid_type_for_array() {
1600 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1601 container.get_slice_mut_at(24, 2048 - 24).unwrap().fill(14);
1602
1603 fn become_array<S: ArraySlotKind>(
1604 container: &mut Container,
1605 format: ArrayFormat,
1606 ) -> Result<Block<&mut Container, Array<S>>, Error> {
1607 get_reserved_of_order(container, 4).become_array_value::<S>(
1608 4,
1609 format,
1610 BlockIndex::EMPTY,
1611 BlockIndex::EMPTY,
1612 )
1613 }
1614
1615 assert!(become_array::<Int>(&mut container, ArrayFormat::Default).is_ok());
1616 assert!(become_array::<Uint>(&mut container, ArrayFormat::Default).is_ok());
1617 assert!(become_array::<Double>(&mut container, ArrayFormat::Default).is_ok());
1618 assert!(become_array::<StringRef>(&mut container, ArrayFormat::Default).is_ok());
1619
1620 for format in [ArrayFormat::LinearHistogram, ArrayFormat::ExponentialHistogram] {
1621 assert!(become_array::<Int>(&mut container, format).is_ok());
1622 assert!(become_array::<Uint>(&mut container, format).is_ok());
1623 assert!(become_array::<Double>(&mut container, format).is_ok());
1624 assert!(become_array::<StringRef>(&mut container, format).is_err());
1625 }
1626 }
1627
1628 #[fuchsia::test]
1634 fn test_string_arrays() {
1635 let (mut container, _storage) = Container::read_and_write(2048).unwrap();
1636 container.get_slice_mut_at(48, 2048 - 48).unwrap().fill(14);
1637
1638 let parent_index = BlockIndex::new(0);
1639 let name_index = BlockIndex::new(1);
1640 let mut block = get_reserved(&mut container)
1641 .become_array_value::<StringRef>(4, ArrayFormat::Default, name_index, parent_index)
1642 .unwrap();
1643
1644 for i in 0..4 {
1645 block.set_string_slot(i, ((i + 4) as u32).into());
1646 }
1647
1648 for i in 0..4 {
1649 let read_index = block.get_string_index_at(i).unwrap();
1650 assert_eq!(*read_index, (i + 4) as u32);
1651 }
1652
1653 assert_8_bytes!(
1654 container,
1655 0,
1656 [
1657 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
1660 ]
1661 );
1662 assert_8_bytes!(container, 8, [0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1663 for i in 0..4 {
1664 let slice = container.get_slice_at(16 + (i * 4), 4).unwrap();
1665 assert_eq!(slice, [(i as u8 + 4), 0x00, 0x00, 0x00]);
1666 }
1667 }
1668
1669 #[fuchsia::test]
1670 fn become_array() {
1671 let (mut container, _storage) = Container::read_and_write(128).unwrap();
1673 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1674
1675 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1676 .unwrap()
1677 .become_reserved()
1678 .become_array_value::<Int>(
1679 14,
1680 ArrayFormat::Default,
1681 BlockIndex::EMPTY,
1682 BlockIndex::EMPTY,
1683 )
1684 .unwrap();
1685 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1686 slice
1687 .iter()
1688 .enumerate()
1689 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1690
1691 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1692 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1693 .unwrap()
1694 .become_reserved()
1695 .become_array_value::<Int>(
1696 14,
1697 ArrayFormat::LinearHistogram,
1698 BlockIndex::EMPTY,
1699 BlockIndex::EMPTY,
1700 )
1701 .unwrap();
1702 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1703 slice
1704 .iter()
1705 .enumerate()
1706 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1707
1708 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1709 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1710 .unwrap()
1711 .become_reserved()
1712 .become_array_value::<Int>(
1713 14,
1714 ArrayFormat::ExponentialHistogram,
1715 BlockIndex::EMPTY,
1716 BlockIndex::EMPTY,
1717 )
1718 .unwrap();
1719 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1720 slice
1721 .iter()
1722 .enumerate()
1723 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1724
1725 container.get_slice_mut_at(16, 128 - 16).unwrap().fill(1);
1726 let _ = Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1727 .unwrap()
1728 .become_reserved()
1729 .become_array_value::<StringRef>(
1730 28,
1731 ArrayFormat::Default,
1732 BlockIndex::EMPTY,
1733 BlockIndex::EMPTY,
1734 )
1735 .unwrap();
1736 let slice = container.get_slice_at(16, 128 - 16).unwrap();
1737 slice
1738 .iter()
1739 .enumerate()
1740 .for_each(|(index, i)| assert_eq!(*i, 0, "failed: byte = {} at index {}", *i, index));
1741 }
1742
1743 #[fuchsia::test]
1744 fn uint_array_value() {
1745 let (mut container, _storage) =
1746 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1747 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1748 .unwrap()
1749 .become_reserved()
1750 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1751 .unwrap();
1752
1753 assert_eq!(block.block_type(), Some(BlockType::ArrayValue));
1754 assert_eq!(*block.parent_index(), 2);
1755 assert_eq!(*block.name_index(), 3);
1756 assert_eq!(block.format(), Some(ArrayFormat::LinearHistogram));
1757 assert_eq!(block.slots(), 4);
1758 assert_eq!(block.entry_type(), Some(BlockType::UintValue));
1759
1760 for i in 0..4 {
1761 block.set(i, (i as u64 + 1) * 5);
1762 }
1763 block.set(4, 3);
1764 block.set(7, 5);
1765
1766 assert_8_bytes!(container, 0, [0x02, 0x0b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00]);
1767 assert_8_bytes!(container, 8, [0x15, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1768 for i in 0..4 {
1769 assert_8_bytes!(
1770 container,
1771 8 * (i + 2),
1772 [(i as u8 + 1) * 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1773 );
1774 }
1775
1776 let (mut bad_container, _storage) =
1777 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1778 let mut bad_bytes = [0u8; constants::MIN_ORDER_SIZE];
1779 container.copy_bytes(&mut bad_bytes[..]);
1780 bad_bytes[8] = 0x12; bad_container.copy_from_slice(&bad_bytes);
1782 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1783 assert_eq!(bad_block.format(), Some(ArrayFormat::LinearHistogram));
1784 assert_eq!(bad_block.entry_type(), None);
1786
1787 bad_bytes[8] = 0xef; bad_container.copy_from_slice(&bad_bytes);
1789 let bad_block = Block::<_, Array<Uint>>::new(&bad_container, BlockIndex::EMPTY);
1790 assert_eq!(bad_block.format(), None);
1791 assert_eq!(bad_block.entry_type(), None);
1792
1793 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1794 for i in 0..4 {
1795 assert_eq!(block.get(i), Some((i as u64 + 1) * 5));
1796 }
1797 assert_eq!(block.get(4), None);
1798 }
1799
1800 #[fuchsia::test]
1801 fn array_slots_bigger_than_block_order() {
1802 let (mut container, _storage) =
1803 Container::read_and_write(constants::MAX_ORDER_SIZE).unwrap();
1804 assert!(
1807 Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1808 .unwrap()
1809 .become_reserved()
1810 .become_array_value::<Int>(257, ArrayFormat::Default, 1.into(), 2.into())
1811 .is_err()
1812 );
1813 assert!(
1814 Block::free(&mut container, BlockIndex::EMPTY, 7, BlockIndex::EMPTY)
1815 .unwrap()
1816 .become_reserved()
1817 .become_array_value::<Int>(254, ArrayFormat::Default, 1.into(), 2.into())
1818 .is_ok()
1819 );
1820
1821 assert!(
1824 Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1825 .unwrap()
1826 .become_reserved()
1827 .become_array_value::<Int>(8, ArrayFormat::Default, 1.into(), 2.into())
1828 .is_err()
1829 );
1830 assert!(
1831 Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1832 .unwrap()
1833 .become_reserved()
1834 .become_array_value::<Int>(6, ArrayFormat::Default, 1.into(), 2.into())
1835 .is_ok()
1836 );
1837 }
1838
1839 #[fuchsia::test]
1840 fn array_clear() {
1841 let (mut container, _storage) =
1842 Container::read_and_write(constants::MIN_ORDER_SIZE * 4).unwrap();
1843
1844 let sample = [0xff, 0xff, 0xff];
1846 container.copy_from_slice_at(48, &sample);
1847
1848 let mut block = Block::free(&mut container, BlockIndex::EMPTY, 2, BlockIndex::EMPTY)
1849 .unwrap()
1850 .become_reserved()
1851 .become_array_value::<Uint>(4, ArrayFormat::LinearHistogram, 3.into(), 2.into())
1852 .unwrap();
1853
1854 for i in 0..4 {
1855 block.set(i, (i + 1) as u64);
1856 }
1857
1858 block.clear(1);
1859
1860 assert_eq!(1, block.get(0).expect("get uint 0"));
1861 assert_8_bytes!(container, 16, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1862
1863 for i in 1..4 {
1864 let block = container.block_at_unchecked::<Array<Uint>>(BlockIndex::EMPTY);
1865 assert_eq!(0, block.get(i).expect("get uint"));
1866 assert_8_bytes!(
1867 container,
1868 16 + (i * 8),
1869 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1870 );
1871 }
1872
1873 let slice = container.get_slice_at(48, 3).unwrap();
1875 assert_eq!(slice, &sample[..]);
1876 }
1877
1878 #[fuchsia::test]
1879 fn become_link() {
1880 let (mut container, _storage) =
1881 Container::read_and_write(constants::MIN_ORDER_SIZE).unwrap();
1882 let block = get_reserved(&mut container).become_link(
1883 BlockIndex::new(1),
1884 BlockIndex::new(2),
1885 BlockIndex::new(3),
1886 LinkNodeDisposition::Inline,
1887 );
1888 assert_eq!(*block.name_index(), 1);
1889 assert_eq!(*block.parent_index(), 2);
1890 assert_eq!(*block.content_index(), 3);
1891 assert_eq!(block.block_type(), Some(BlockType::LinkValue));
1892 assert_eq!(block.link_node_disposition(), Some(LinkNodeDisposition::Inline));
1893 assert_8_bytes!(container, 0, [0x01, 0x0c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00]);
1894 assert_8_bytes!(container, 8, [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]);
1895 }
1896
1897 #[test]
1898 fn array_capacity_numeric() {
1899 assert_eq!(2, max_array_capacity::<Int>(1));
1900 assert_eq!(2 + 4, max_array_capacity::<Int>(2));
1901 assert_eq!(2 + 4 + 8, max_array_capacity::<Int>(3));
1902 assert_eq!(2 + 4 + 8 + 16, max_array_capacity::<Int>(4));
1903 assert_eq!(2 + 4 + 8 + 16 + 32, max_array_capacity::<Int>(5));
1904 assert_eq!(2 + 4 + 8 + 16 + 32 + 64, max_array_capacity::<Int>(6));
1905 assert_eq!(2 + 4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<Int>(7),);
1906 }
1907
1908 #[test]
1909 fn array_capacity_string_reference() {
1910 assert_eq!(4, max_array_capacity::<StringRef>(1));
1911 assert_eq!(4 + 8, max_array_capacity::<StringRef>(2));
1912 assert_eq!(4 + 8 + 16, max_array_capacity::<StringRef>(3));
1913 assert_eq!(4 + 8 + 16 + 32, max_array_capacity::<StringRef>(4));
1914 assert_eq!(4 + 8 + 16 + 32 + 64, max_array_capacity::<StringRef>(5));
1915 assert_eq!(4 + 8 + 16 + 32 + 64 + 128, max_array_capacity::<StringRef>(6));
1916 assert_eq!(4 + 8 + 16 + 32 + 64 + 128 + 256, max_array_capacity::<StringRef>(7));
1917 }
1918
1919 fn get_header(container: &mut Container, size: usize) -> Block<&mut Container, Header> {
1920 get_reserved(container).become_header(size).unwrap()
1921 }
1922
1923 fn get_reserved(container: &mut Container) -> Block<&mut Container, Reserved> {
1924 get_reserved_of_order(container, 1)
1925 }
1926
1927 fn get_reserved_of_order(
1928 container: &mut Container,
1929 order: u8,
1930 ) -> Block<&mut Container, Reserved> {
1931 let block = Block::free(container, BlockIndex::EMPTY, order, BlockIndex::new(0)).unwrap();
1932 block.become_reserved()
1933 }
1934}