1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Definitions for all the block types.

use num_derive::{FromPrimitive, ToPrimitive};
use std::fmt;

/// The type of a block.
#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd, FromPrimitive, ToPrimitive)]
#[repr(u8)]
pub enum BlockType {
    /// Contains index of the next free block of the same order.
    Free = 0,

    /// Available to be changed to a different class. Transitonal.
    Reserved = 1,

    /// One header at the beginning of the VMO region. Index 0.
    Header = 2,

    /// An entry in the tree, which might hold nodes, metrics or properties.
    /// Contains a reference count.
    NodeValue = 3,

    /// Numeric properties.
    IntValue = 4,
    UintValue = 5,
    DoubleValue = 6,

    /// String or bytevector property value.
    BufferValue = 7,

    /// Contains a string payload.
    Extent = 8,

    /// Gives blocks a human-readable identifier.
    Name = 9,

    /// A deleted object
    Tombstone = 10,

    /// An array value
    ArrayValue = 11,

    /// A link value
    LinkValue = 12,

    /// A boolean value
    BoolValue = 13,

    /// A string reference value.
    StringReference = 14,
}

impl fmt::Display for BlockType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            BlockType::Free => write!(f, "FREE"),
            BlockType::Reserved => write!(f, "RESERVED"),
            BlockType::Header => write!(f, "HEADER"),
            BlockType::NodeValue => write!(f, "NODE_VALUE"),
            BlockType::IntValue => write!(f, "INT_VALUE"),
            BlockType::UintValue => write!(f, "UINT_VALUE"),
            BlockType::DoubleValue => write!(f, "DOUBLE_VALUE"),
            BlockType::BufferValue => write!(f, "BUFFER_VALUE"),
            BlockType::Extent => write!(f, "EXTENT"),
            BlockType::Name => write!(f, "NAME"),
            BlockType::Tombstone => write!(f, "TOMBSTONE"),
            BlockType::ArrayValue => write!(f, "ARRAY_VALUE"),
            BlockType::LinkValue => write!(f, "LINK_VALUE"),
            BlockType::BoolValue => write!(f, "BOOL_VALUE"),
            BlockType::StringReference => write!(f, "STRING_REFERENCE"),
        }
    }
}

impl BlockType {
    /// Returns whether the type is for a `*_VALUE` block or not.
    pub fn is_any_value(&self) -> bool {
        matches!(
            *self,
            BlockType::NodeValue
                | BlockType::IntValue
                | BlockType::UintValue
                | BlockType::DoubleValue
                | BlockType::BufferValue
                | BlockType::ArrayValue
                | BlockType::LinkValue
                | BlockType::BoolValue
        )
    }

    /// Returns whether the type is of a numeric `*_VALUE` block or not.
    pub fn is_numeric_value(&self) -> bool {
        matches!(*self, BlockType::IntValue | BlockType::UintValue | BlockType::DoubleValue)
    }

    pub fn is_valid_for_array(&self) -> bool {
        matches!(*self, BlockType::StringReference) || self.is_numeric_value()
    }

    /// The number of bytes an element requires.
    /// Returns `None` if `!self.is_valid_for_array()`.
    pub fn array_element_size(&self) -> Option<usize> {
        if self.is_numeric_value() {
            Some(std::mem::size_of::<u64>())
        } else if matches!(self, BlockType::StringReference) {
            Some(std::mem::size_of::<u32>())
        } else {
            None
        }
    }

    /// Returns an array of all the types.
    #[cfg(test)]
    pub fn all() -> [BlockType; 15] {
        [
            BlockType::Free,
            BlockType::Reserved,
            BlockType::Header,
            BlockType::NodeValue,
            BlockType::IntValue,
            BlockType::UintValue,
            BlockType::DoubleValue,
            BlockType::BufferValue,
            BlockType::Extent,
            BlockType::Name,
            BlockType::Tombstone,
            BlockType::ArrayValue,
            BlockType::LinkValue,
            BlockType::BoolValue,
            BlockType::StringReference,
        ]
    }
}