1use crate::types::{variant::*, variant_type_id::*, StatusCode};
2
3#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub struct Array {
8 pub value_type: VariantTypeId,
10
11 pub values: Vec<Variant>,
13
14 pub dimensions: Option<Vec<u32>>,
19}
20
21impl Array {
22 pub fn new<V>(value_type: VariantTypeId, values: V) -> Result<Array, StatusCode>
24 where
25 V: Into<Vec<Variant>>,
26 {
27 let values = values.into();
28 if Self::validate_array_type_to_values(value_type, &values) {
29 Ok(Array {
30 value_type,
31 values,
32 dimensions: None,
33 })
34 } else {
35 Err(StatusCode::BadDecodingError)
36 }
37 }
38
39 pub fn new_multi<V, D>(
43 value_type: VariantTypeId,
44 values: V,
45 dimensions: D,
46 ) -> Result<Array, StatusCode>
47 where
48 V: Into<Vec<Variant>>,
49 D: Into<Vec<u32>>,
50 {
51 let values = values.into();
52 let dimensions = dimensions.into();
53
54 if Self::validate_array_type_to_values(value_type, &values) {
56 Ok(Array {
57 value_type,
58 values,
59 dimensions: Some(dimensions),
60 })
61 } else {
62 Err(StatusCode::BadDecodingError)
63 }
64 }
65
66 fn validate_array_type_to_values(value_type: VariantTypeId, values: &[Variant]) -> bool {
68 match value_type {
69 VariantTypeId::Array | VariantTypeId::Empty => {
70 error!("Invalid array type supplied");
71 false
72 }
73 _ => {
74 if !values_are_of_type(values, value_type) {
75 error!("Value type of array does not match contents");
77 false
78 } else {
79 true
80 }
81 }
82 }
83 }
84
85 pub fn is_valid(&self) -> bool {
86 self.is_valid_dimensions() && Self::array_is_valid(&self.values)
87 }
88
89 pub fn encoding_mask(&self) -> u8 {
90 let mut encoding_mask = self.value_type.encoding_mask();
91 encoding_mask |= EncodingMask::ARRAY_VALUES_BIT;
92 if self.dimensions.is_some() {
93 encoding_mask |= EncodingMask::ARRAY_DIMENSIONS_BIT;
94 }
95 encoding_mask
96 }
97
98 fn array_is_valid(values: &[Variant]) -> bool {
100 if values.is_empty() {
101 true
102 } else {
103 let expected_type_id = values[0].type_id();
104 if expected_type_id == VariantTypeId::Array {
105 error!("Variant array contains nested array {:?}", expected_type_id);
107 false
108 } else if values.len() > 1 {
109 values_are_of_type(&values[1..], expected_type_id)
110 } else {
111 true
113 }
114 }
115 }
116
117 fn validate_dimensions(values_len: usize, dimensions: &[u32]) -> bool {
118 let mut length: usize = 1;
120 for d in dimensions {
121 if *d == 0 {
123 continue;
125 }
126 length *= *d as usize;
127 }
128 length <= values_len
129 }
130
131 fn is_valid_dimensions(&self) -> bool {
132 if let Some(ref dimensions) = self.dimensions {
133 Self::validate_dimensions(self.values.len(), dimensions)
134 } else {
135 true
136 }
137 }
138}
139
140pub fn values_are_of_type(values: &[Variant], expected_type: VariantTypeId) -> bool {
142 let found_unexpected = values.iter().any(|v| v.type_id() != expected_type);
144 if found_unexpected {
145 error!(
146 "Variant array's type is expected to be {:?} but found other types in it",
147 expected_type
148 );
149 };
150 !found_unexpected
151}