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