inspect_format/
block.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Utilities for writing VMO blocks in a type-safe way.
6
7use 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/// Disposition of a Link value.
24#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
25#[repr(u8)]
26pub enum LinkNodeDisposition {
27    Child = 0,
28    Inline = 1,
29}
30
31/// Format in which the property will be read.
32#[derive(Debug, PartialEq, Eq, FromPrimitive)]
33#[repr(u8)]
34pub enum PropertyFormat {
35    String = 0,
36    Bytes = 1,
37    StringReference = 2,
38}
39
40/// Points to an index in the VMO and reads it according to the bytes in it.
41#[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    /// Creates a new block.
50    #[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        // TODO(https://fxbug.dev/392965471): bring back when we have BlockIndex<K>.
72        // debug_assert_eq!(this.block_type(), Some(K::block_type()));
73    }
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    /// Returns index of the block in the vmo.
218    pub fn index(&self) -> BlockIndex {
219        self.index
220    }
221
222    /// Returns the order of the block.
223    pub fn order(&self) -> u8 {
224        HeaderFields::order(self)
225    }
226
227    /// Returns the type of a block.
228    pub fn block_type(&self) -> Option<BlockType> {
229        let block_type = self.block_type_raw();
230        BlockType::from_u8(block_type)
231    }
232
233    /// Returns the type of a block.
234    pub fn block_type_raw(&self) -> u8 {
235        HeaderFields::block_type(self)
236    }
237
238    /// Get the offset of the payload in the container.
239    pub(crate) fn payload_offset(&self) -> usize {
240        self.index.offset() + constants::HEADER_SIZE_BYTES
241    }
242
243    /// Get the offset of the header in the container.
244    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    /// Returns the magic number in a HEADER block.
279    pub fn magic_number(&self) -> u32 {
280        HeaderFields::header_magic(self)
281    }
282
283    /// Returns the version of a HEADER block.
284    pub fn version(&self) -> u32 {
285        HeaderFields::header_version(self)
286    }
287
288    /// Returns the generation count of a HEADER block.
289    pub fn generation_count(&self) -> u64 {
290        PayloadFields::value(self)
291    }
292
293    /// Returns the size of the part of the VMO that is currently allocated. The size
294    /// is saved in a field in the HEADER block.
295    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    /// True if the header is locked, false otherwise.
305    pub fn is_locked(&self) -> bool {
306        PayloadFields::value(self) & 1 == 1
307    }
308
309    /// Check if the HEADER block is locked (when generation count is odd).
310    /// NOTE: this should only be used for testing.
311    #[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    /// Gets the double value of a DOUBLE_VALUE block.
325    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    /// Gets the value of an INT_VALUE block.
332    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    /// Gets the unsigned value of a UINT_VALUE block.
339    pub fn value(&self) -> u64 {
340        PayloadFields::value(self)
341    }
342}
343
344impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Bool> {
345    /// Gets the bool values of a BOOL_VALUE block.
346    pub fn value(&self) -> bool {
347        PayloadFields::value(self) != 0
348    }
349}
350
351impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Buffer> {
352    /// Gets the index of the EXTENT of the PROPERTY block.
353    pub fn extent_index(&self) -> BlockIndex {
354        PayloadFields::property_extent_index(self).into()
355    }
356
357    /// Gets the total length of a PROPERTY or STRING_REFERERENCE block.
358    pub fn total_length(&self) -> usize {
359        PayloadFields::property_total_length(self) as usize
360    }
361
362    /// Gets the flags of a PROPERTY block.
363    pub fn format(&self) -> Option<PropertyFormat> {
364        let raw_format = PayloadFields::property_flags(self);
365        PropertyFormat::from_u8(raw_format)
366    }
367
368    /// Gets the flags of a PROPERTY block.
369    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    /// Gets the total length of a PROPERTY or STRING_REFERERENCE block.
376    pub fn total_length(&self) -> usize {
377        PayloadFields::property_total_length(self) as usize
378    }
379
380    /// Returns the next EXTENT in an EXTENT chain.
381    pub fn next_extent(&self) -> BlockIndex {
382        HeaderFields::extent_next_index(self).into()
383    }
384
385    /// Returns the current reference count of a string reference.
386    pub fn reference_count(&self) -> u32 {
387        HeaderFields::string_reference_count(self)
388    }
389
390    /// Read the inline portion of a STRING_REFERENCE
391    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    /// Returns the next EXTENT in an EXTENT chain.
406    pub fn next_extent(&self) -> BlockIndex {
407        HeaderFields::extent_next_index(self).into()
408    }
409
410    /// Returns the payload bytes value of an EXTENT block.
411    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    /// Gets the format of an ARRAY_VALUE block.
420    pub fn format(&self) -> Option<ArrayFormat> {
421        let raw_flags = PayloadFields::array_flags(self);
422        ArrayFormat::from_u8(raw_flags)
423    }
424
425    /// Gets the number of slots in an ARRAY_VALUE block.
426    pub fn slots(&self) -> usize {
427        PayloadFields::array_slots_count(self) as usize
428    }
429
430    /// Get the array capacity size for the given |order|.
431    pub fn capacity(&self) -> Option<usize> {
432        self.entry_type_size().map(|size| array_capacity(size, self.order()))
433    }
434
435    /// Gets the type of each slot in an ARRAY_VALUE block.
436    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    /// Gets the type of each slot in an ARRAY_VALUE block.
442    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    /// Gets the value of an int ARRAY_VALUE slot.
469    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    /// Gets the value of a double ARRAY_VALUE slot.
480    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    /// Gets the value of a uint ARRAY_VALUE slot.
491    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    /// Gets the index of the content of this LINK_VALUE block.
502    pub fn content_index(&self) -> BlockIndex {
503        PayloadFields::content_index(self).into()
504    }
505
506    /// Gets the node disposition of a LINK_VALUE block.
507    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    /// Gets the NAME block index of a *_VALUE block.
515    pub fn name_index(&self) -> BlockIndex {
516        HeaderFields::value_name_index(self).into()
517    }
518
519    /// Get the parent block index of a *_VALUE block.
520    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    /// Get the child count of a NODE_VALUE block.
527    pub fn child_count(&self) -> u64 {
528        PayloadFields::value(self)
529    }
530}
531
532impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Tombstone> {
533    /// Get the child count of a TOMBSTONE block.
534    pub fn child_count(&self) -> u64 {
535        PayloadFields::value(self)
536    }
537}
538
539impl<T: Deref<Target = Q>, Q: ReadBytes> Block<T, Free> {
540    /// Get next free block
541    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    /// Get the length of the name of a NAME block
548    pub fn length(&self) -> usize {
549        HeaderFields::name_length(self).into()
550    }
551
552    /// Returns the contents of a NAME block.
553    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    /// Converts a block to a FREE block
566    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    /// Set the order of the block.
579    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    /// Write |bytes| to the payload section of the block in the container.
588    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    /// Initializes an empty free block.
596    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    /// Converts a FREE block to a RESERVED block
614    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    /// Set the next free block.
621    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    /// Initializes a HEADER block.
628    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        // Safety: a valid `size` is smaller than a u32
638        this.set_vmo_size(size.try_into().unwrap())?;
639        Ok(this)
640    }
641
642    /// Converts a block to an EXTENT block.
643    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    /// Converts a RESERVED block into a DOUBLE_VALUE block.
650    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    /// Converts a RESERVED block into an INT_VALUE block.
664    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    /// Converts a RESERVED block into a UINT_VALUE block.
678    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    /// Converts a RESERVED block into a BOOL_VALUE block.
692    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    /// Initializes a NODE_VALUE block.
706    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    /// Converts a *_VALUE block into a BUFFER_VALUE block.
717    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    /// Initializes a STRING_REFERENCE block. Everything is set except for
730    /// the payload string and total length.
731    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    /// Creates a NAME block.
739    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            // Make sure we didn't split a multibyte UTF-8 character; if so, delete the fragment.
745            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        // Safety: name length must fit in 12 bytes.
751        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    /// Creates a LINK block.
757    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    /// Converts a block to an *_ARRAY_VALUE block
772    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    /// Initializes a *_VALUE block header.
800    #[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    /// Allows to set the magic value of the header.
816    /// NOTE: this should only be used for testing.
817    #[doc(hidden)]
818    pub fn set_magic(&mut self, value: u32) {
819        HeaderFields::set_header_magic(self, value);
820    }
821
822    /// Set the size of the part of the VMO that is currently allocated. The size is saved in
823    /// a field in the HEADER block.
824    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    /// Freeze the HEADER, indicating a VMO is frozen.
836    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    /// Thaw the HEADER, indicating a VMO is Live again.
843    pub fn thaw(&mut self, gen: u64) {
844        PayloadFields::set_value(self, gen)
845    }
846
847    /// Lock a HEADER block
848    pub fn lock(&mut self) {
849        self.check_locked(false);
850        self.increment_generation_count();
851        fence(Ordering::Acquire);
852    }
853
854    /// Unlock a HEADER block
855    pub fn unlock(&mut self) {
856        self.check_locked(true);
857        fence(Ordering::Release);
858        self.increment_generation_count();
859    }
860
861    /// Increment generation counter in a HEADER block for locking/unlocking
862    fn increment_generation_count(&mut self) {
863        let value = PayloadFields::value(self);
864        // TODO(miguelfrde): perform this in place using overflowing add.
865        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    /// Initializes a TOMBSTONE block.
872    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    /// Set the child count of a NODE_VALUE block.
879    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    /// Sets all values of the array to zero starting on `start_slot_index` (inclusive).
888    pub fn clear(&mut self, start_slot_index: usize) {
889        let array_slots = self.slots() - start_slot_index;
890        // TODO(https://fxbug.dev/392965471): this can come back when we improve the BlockIndex<K>
891        // stuff.
892        // let type_size = S::array_entry_type_size();
893        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    /// Sets the value of a string ARRAY_VALUE block.
905    pub fn set_string_slot(&mut self, slot_index: usize, string_index: BlockIndex) {
906        if slot_index >= self.slots() {
907            return;
908        }
909        // 0 is used as special value; the reader won't dereference it
910        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    /// Sets the value of an int ARRAY_VALUE block.
917    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    /// Sets the value of a double ARRAY_VALUE block.
930    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    /// Sets the value of a uint ARRAY_VALUE block.
941    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    /// Sets the index of the next EXTENT in the chain.
952    pub fn set_next_index(&mut self, next_extent_index: BlockIndex) {
953        HeaderFields::set_extent_next_index(self, *next_extent_index);
954    }
955
956    /// Set the payload of an EXTENT block. The number of bytes written will be returned.
957    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    /// Sets the index of the next EXTENT in the chain.
971    pub fn set_next_index(&mut self, next_extent_index: BlockIndex) {
972        HeaderFields::set_extent_next_index(self, *next_extent_index);
973    }
974
975    /// Sets the total length of a BUFFER_VALUE or STRING_REFERENCE block.
976    pub fn set_total_length(&mut self, length: u32) {
977        PayloadFields::set_property_total_length(self, length);
978    }
979
980    /// Increment the reference count by 1.
981    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    /// Decrement the reference count by 1.
989    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    /// Write the portion of the string that fits into the STRING_REFERENCE block,
997    /// as well as write the total length of value to the block.
998    /// Returns the number of bytes written.
999    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        // we do not care about splitting multibyte UTF-8 characters, because the rest
1005        // of the split will go in an extent and be joined together at read time.
1006        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    /// Sets the value of a DOUBLE_VALUE block.
1018    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    /// Sets the value of a INT_VALUE block.
1025    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    /// Sets the value of a UINT_VALUE block.
1032    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    /// Sets the value of a BOOL_VALUE block.
1039    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    /// Sets the total length of a BUFFER_VALUE block.
1046    pub fn set_total_length(&mut self, length: u32) {
1047        PayloadFields::set_property_total_length(self, length);
1048    }
1049
1050    /// Sets the index of the EXTENT of a BUFFER_VALUE block.
1051    pub fn set_extent_index(&mut self, index: BlockIndex) {
1052        // TODO(https://fxbug.dev/392965471): this should probably take a reference to a
1053        // Block<Extent> to guarantee the index is valid.
1054        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    /// Set the child count of a NODE_VALUE block.
1060    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
1073/// Get the array capacity size for the given |order|.
1074fn 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 // with order == 0, only 4 bytes will be inlined
1191        );
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        // Should be possible to handle headers without size.
1255        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        // Set vmo size should have no effect.
1259        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        // Can't unlock unlocked header.
1296        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        // Can't lock locked header.
1307        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        // set payload bytes to max u64 value. Ensure we cannot lock
1315        // and after unlocking, the value is zero.
1316        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        // Test overflow: Ensure that after unlocking, the value is zero.
1346        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); // Check we copied correctly
1573        assert!(bad_block.contents().is_err()); // Make sure we get Error not panic
1574
1575        // Test to make sure UTF8 strings are truncated safely if they're too long for the block,
1576        // even if the last character is multibyte and would be chopped in the middle.
1577        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    // In this test, we actually don't care about generating string reference
1626    // blocks at all. That is tested elsewhere. All we care about is that the indexes
1627    // put in a certain slot come out of the slot correctly. Indexes are u32, so
1628    // for simplicity this test just uses meaningless numbers instead of creating actual
1629    // indexable string reference values.
1630    #[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, /* parent */
1655                0x00, 0x00, 0x01, /* name_index */
1656                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        // primarily these tests are making sure that arrays clear their payload space
1669        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; // LinearHistogram; Header
1778        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        // Make sure we get Error not panic or BlockType::Header
1782        assert_eq!(bad_block.entry_type(), None);
1783
1784        bad_bytes[8] = 0xef; // Not in enum; Not in enum
1785        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        // A block of size 7 (max) can hold 254 values: 2048B - 8B (header) - 8B (array metadata)
1802        // gives 2032, which means 254 values of 8 bytes each maximum.
1803        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        // A block of size 2 can hold 6 values: 64B - 8B (header) - 8B (array metadata)
1815        // gives 48, which means 6 values of 8 bytes each maximum.
1816        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        // Write some sample data in the container after the slot fields.
1834        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        // Sample data shouldn't have been overwritten
1863        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}