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