Skip to main content

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::{Ordering, fence};
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, generation: u64) {
844        PayloadFields::set_value(self, generation)
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        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    /// Decrement the reference count by 1.
992    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    /// Write the portion of the string that fits into the STRING_REFERENCE block,
1000    /// as well as write the total length of value to the block.
1001    /// Returns the number of bytes written.
1002    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        // we do not care about splitting multibyte UTF-8 characters, because the rest
1008        // of the split will go in an extent and be joined together at read time.
1009        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    /// Sets the value of a DOUBLE_VALUE block.
1021    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    /// Sets the value of a INT_VALUE block.
1028    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    /// Sets the value of a UINT_VALUE block.
1035    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    /// Sets the value of a BOOL_VALUE block.
1042    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    /// Sets the total length of a BUFFER_VALUE block.
1049    pub fn set_total_length(&mut self, length: u32) {
1050        PayloadFields::set_property_total_length(self, length);
1051    }
1052
1053    /// Sets the index of the EXTENT of a BUFFER_VALUE block.
1054    pub fn set_extent_index(&mut self, index: BlockIndex) {
1055        // TODO(https://fxbug.dev/392965471): this should probably take a reference to a
1056        // Block<Extent> to guarantee the index is valid.
1057        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    /// Set the child count of a NODE_VALUE block.
1063    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
1076/// Get the array capacity size for the given |order|.
1077fn 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 // with order == 0, only 4 bytes will be inlined
1194        );
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        // Should be possible to handle headers without size.
1258        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        // Set vmo size should have no effect.
1262        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        // Can't unlock unlocked header.
1299        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        // Can't lock locked header.
1310        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        // set payload bytes to max u64 value. Ensure we cannot lock
1318        // and after unlocking, the value is zero.
1319        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        // Test overflow: Ensure that after unlocking, the value is zero.
1349        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); // Check we copied correctly
1576        assert!(bad_block.contents().is_err()); // Make sure we get Error not panic
1577
1578        // Test to make sure UTF8 strings are truncated safely if they're too long for the block,
1579        // even if the last character is multibyte and would be chopped in the middle.
1580        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    // In this test, we actually don't care about generating string reference
1629    // blocks at all. That is tested elsewhere. All we care about is that the indexes
1630    // put in a certain slot come out of the slot correctly. Indexes are u32, so
1631    // for simplicity this test just uses meaningless numbers instead of creating actual
1632    // indexable string reference values.
1633    #[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, /* parent */
1658                0x00, 0x00, 0x01, /* name_index */
1659                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        // primarily these tests are making sure that arrays clear their payload space
1672        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; // LinearHistogram; Header
1781        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        // Make sure we get Error not panic or BlockType::Header
1785        assert_eq!(bad_block.entry_type(), None);
1786
1787        bad_bytes[8] = 0xef; // Not in enum; Not in enum
1788        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        // A block of size 7 (max) can hold 254 values: 2048B - 8B (header) - 8B (array metadata)
1805        // gives 2032, which means 254 values of 8 bytes each maximum.
1806        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        // A block of size 2 can hold 6 values: 64B - 8B (header) - 8B (array metadata)
1822        // gives 48, which means 6 values of 8 bytes each maximum.
1823        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        // Write some sample data in the container after the slot fields.
1845        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        // Sample data shouldn't have been overwritten
1874        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}