1use crate::core::{strings::*, Handle, UndefinedStruct};
2use crate::SMBiosStruct;
3use serde::{ser::SerializeSeq, ser::SerializeStruct, Serialize, Serializer};
4use std::fmt;
5
6pub struct SMBiosGroupAssociations<'a> {
16 parts: &'a UndefinedStruct,
17}
18
19impl<'a> SMBiosStruct<'a> for SMBiosGroupAssociations<'a> {
20 const STRUCT_TYPE: u8 = 14u8;
21
22 fn new(parts: &'a UndefinedStruct) -> Self {
23 Self { parts }
24 }
25
26 fn parts(&self) -> &'a UndefinedStruct {
27 self.parts
28 }
29}
30
31impl<'a> SMBiosGroupAssociations<'a> {
32 pub fn group_name(&self) -> SMBiosString {
34 self.parts.get_field_string(0x4)
35 }
36
37 pub fn number_of_items(&self) -> Option<usize> {
39 let length = self.parts.header.length() as usize;
40
41 if length < GroupAssociationItemIterator::ITEMS_OFFSET {
42 return None;
43 }
44
45 let byte_count = length - GroupAssociationItemIterator::ITEMS_OFFSET;
46
47 if byte_count % GroupAssociationItem::SIZE != 0 {
48 return None;
49 }
50
51 Some(byte_count / GroupAssociationItem::SIZE)
52 }
53
54 pub fn item_iterator(&'a self) -> GroupAssociationItemIterator<'a> {
56 GroupAssociationItemIterator::new(self)
57 }
58}
59
60impl fmt::Debug for SMBiosGroupAssociations<'_> {
61 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
62 fmt.debug_struct(std::any::type_name::<SMBiosGroupAssociations<'_>>())
63 .field("header", &self.parts.header)
64 .field("group_name", &self.group_name())
65 .field("number_of_items", &self.number_of_items())
66 .field("item_iterator", &self.item_iterator())
67 .finish()
68 }
69}
70
71impl Serialize for SMBiosGroupAssociations<'_> {
72 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73 where
74 S: Serializer,
75 {
76 let mut state = serializer.serialize_struct("SMBiosGroupAssociations", 4)?;
77 state.serialize_field("header", &self.parts.header)?;
78 state.serialize_field("group_name", &self.group_name())?;
79 state.serialize_field("number_of_items", &self.number_of_items())?;
80 state.serialize_field("item_iterator", &self.item_iterator())?;
81 state.end()
82 }
83}
84
85pub struct GroupAssociationItem<'a> {
87 group_associations: &'a SMBiosGroupAssociations<'a>,
88 entry_offset: usize,
89}
90
91impl<'a> GroupAssociationItem<'a> {
92 const SIZE: usize = 3usize;
94
95 fn new(group_associations: &'a SMBiosGroupAssociations<'a>, entry_offset: usize) -> Self {
96 Self {
97 group_associations,
98 entry_offset,
99 }
100 }
101
102 pub fn struct_type(&self) -> Option<u8> {
106 self.group_associations
107 .parts()
108 .get_field_byte(self.entry_offset)
109 }
110
111 pub fn item_handle(&self) -> Option<Handle> {
115 self.group_associations
116 .parts()
117 .get_field_handle(self.entry_offset + 1)
118 }
119}
120
121impl fmt::Debug for GroupAssociationItem<'_> {
122 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
123 fmt.debug_struct(std::any::type_name::<GroupAssociationItem<'_>>())
124 .field("struct_type", &self.struct_type())
125 .field("item_handle", &self.item_handle())
126 .finish()
127 }
128}
129
130impl Serialize for GroupAssociationItem<'_> {
131 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
132 where
133 S: Serializer,
134 {
135 let mut state = serializer.serialize_struct("GroupAssociationItem", 2)?;
136 state.serialize_field("struct_type", &self.struct_type())?;
137 state.serialize_field("item_handle", &self.item_handle())?;
138 state.end()
139 }
140}
141
142pub struct GroupAssociationItemIterator<'a> {
144 data: &'a SMBiosGroupAssociations<'a>,
145 current_index: usize,
146 current_entry: usize,
147 number_of_entries: usize,
148}
149
150impl<'a> GroupAssociationItemIterator<'a> {
151 const ITEMS_OFFSET: usize = 5usize;
152
153 fn new(data: &'a SMBiosGroupAssociations<'a>) -> Self {
154 GroupAssociationItemIterator {
155 data: data,
156 current_index: Self::ITEMS_OFFSET,
157 current_entry: 0,
158 number_of_entries: data.number_of_items().unwrap_or(0),
159 }
160 }
161
162 fn reset(&mut self) {
163 self.current_index = Self::ITEMS_OFFSET;
164 self.current_entry = 0;
165 }
166}
167
168impl<'a> IntoIterator for &'a GroupAssociationItemIterator<'a> {
169 type Item = GroupAssociationItem<'a>;
170 type IntoIter = GroupAssociationItemIterator<'a>;
171
172 fn into_iter(self) -> Self::IntoIter {
173 GroupAssociationItemIterator {
174 data: self.data,
175 current_index: GroupAssociationItemIterator::ITEMS_OFFSET,
176 current_entry: 0,
177 number_of_entries: self.data.number_of_items().unwrap_or(0),
178 }
179 }
180}
181
182impl<'a> Iterator for GroupAssociationItemIterator<'a> {
183 type Item = GroupAssociationItem<'a>;
184
185 fn next(&mut self) -> Option<Self::Item> {
186 if self.current_entry == self.number_of_entries {
187 self.reset();
188 return None;
189 }
190
191 let next_index = self.current_index + GroupAssociationItem::SIZE;
192 match self
193 .data
194 .parts()
195 .get_field_data(self.current_index, next_index)
196 {
197 Some(_entry_block) => {
198 let result = GroupAssociationItem::new(self.data, self.current_index);
199 self.current_index = next_index;
200 self.current_entry += 1;
201 Some(result)
202 }
203 None => {
204 self.reset();
205 None
206 }
207 }
208 }
209}
210
211impl<'a> fmt::Debug for GroupAssociationItemIterator<'a> {
212 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
213 fmt.debug_list().entries(self.into_iter()).finish()
214 }
215}
216
217impl<'a> Serialize for GroupAssociationItemIterator<'a> {
218 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
219 where
220 S: Serializer,
221 {
222 let items: Vec<GroupAssociationItem<'_>> = self.into_iter().collect();
223 let mut seq = serializer.serialize_seq(Some(items.len()))?;
224 for e in items {
225 seq.serialize_element(&e)?;
226 }
227 seq.end()
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234
235 #[test]
236 fn unit_test() {
237 let struct_type14 = vec![
238 0x0E, 0x08, 0x5F, 0x00, 0x01, 0xDD, 0x5B, 0x00, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61,
239 0x72, 0x65, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x49, 0x6E, 0x66,
240 0x6F, 0x00, 0x00,
241 ];
242
243 let parts = UndefinedStruct::new(&struct_type14);
244 let test_struct = SMBiosGroupAssociations::new(&parts);
245
246 println!("{:?}", test_struct);
247
248 assert_eq!(
249 test_struct.group_name().to_string(),
250 "Firmware Version Info".to_string()
251 );
252 let mut iterator = test_struct.item_iterator().into_iter();
253 let first_item = iterator.next().unwrap();
254 assert_eq!(first_item.struct_type(), Some(221));
255 assert_eq!(*first_item.item_handle().unwrap(), 91);
256 }
257}