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
138
139
140
141
use crate::variant::*;
use crate::StatusCode;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Array {
pub value_type: VariantTypeId,
pub values: Vec<Variant>,
pub dimensions: Vec<u32>,
}
impl Array {
pub fn new_single<V>(value_type: VariantTypeId, values: V) -> Result<Array, StatusCode>
where
V: Into<Vec<Variant>>,
{
let values = values.into();
if Self::validate_array_type_to_values(value_type, &values) {
Ok(Array {
value_type,
values,
dimensions: Vec::new(),
})
} else {
Err(StatusCode::BadDecodingError)
}
}
pub fn new_multi<V, D>(
value_type: VariantTypeId,
values: V,
dimensions: D,
) -> Result<Array, StatusCode>
where
V: Into<Vec<Variant>>,
D: Into<Vec<u32>>,
{
let values = values.into();
if Self::validate_array_type_to_values(value_type, &values) {
Ok(Array {
value_type,
values,
dimensions: dimensions.into(),
})
} else {
Err(StatusCode::BadDecodingError)
}
}
fn validate_array_type_to_values(value_type: VariantTypeId, values: &[Variant]) -> bool {
match value_type {
VariantTypeId::Array | VariantTypeId::Empty => {
error!("Invalid array type supplied");
false
}
_ => {
if !values_are_of_type(values, value_type) {
error!("Value type of array does not match contents");
false
} else {
true
}
}
}
}
pub fn is_valid(&self) -> bool {
self.is_valid_dimensions() && Self::array_is_valid(&self.values)
}
pub fn has_dimensions(&self) -> bool {
!self.dimensions.is_empty()
}
pub fn encoding_mask(&self) -> u8 {
let mut encoding_mask = self.value_type.encoding_mask();
encoding_mask |= EncodingMask::ARRAY_VALUES_BIT;
if self.has_dimensions() {
encoding_mask |= EncodingMask::ARRAY_DIMENSIONS_BIT;
}
encoding_mask
}
fn array_is_valid(values: &[Variant]) -> bool {
if values.is_empty() {
true
} else {
let expected_type_id = values[0].type_id();
if expected_type_id == VariantTypeId::Array {
error!("Variant array contains nested array {:?}", expected_type_id);
false
} else if values.len() > 1 {
values_are_of_type(&values[1..], expected_type_id)
} else {
true
}
}
}
fn is_valid_dimensions(&self) -> bool {
let mut length: usize = 1;
for d in &self.dimensions {
if *d == 0 {
continue;
}
length *= *d as usize;
}
length <= self.values.len()
}
}
pub fn values_are_of_type(values: &[Variant], expected_type: VariantTypeId) -> bool {
let found_unexpected = values.iter().any(|v| v.type_id() != expected_type);
if found_unexpected {
error!(
"Variant array's type is expected to be {:?} but found other types in it",
expected_type
);
};
!found_unexpected
}