1use crate::error::{PcdError, Result};
16use crate::header::{PcdHeader, ValueType};
17
18#[derive(Debug, Clone, PartialEq)]
19pub struct FieldLayout {
20 pub name: String,
21 pub offset: usize,
22 pub size: usize, pub element_size: usize, pub count: usize,
25 pub type_: ValueType,
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub struct PcdLayout {
30 pub fields: Vec<FieldLayout>,
31 pub total_size: usize,
32}
33
34impl PcdLayout {
35 pub fn from_header(header: &PcdHeader) -> Result<Self> {
36 let mut fields = Vec::with_capacity(header.fields.len());
37 let mut offset = 0;
38
39 for (i, name) in header.fields.iter().enumerate() {
40 let type_char = header
41 .types
42 .get(i)
43 .ok_or_else(|| PcdError::LayoutMismatch {
44 expected: header.fields.len(),
45 got: i,
46 })?;
47
48 let size_in_header = *header
49 .sizes
50 .get(i)
51 .ok_or_else(|| PcdError::LayoutMismatch {
52 expected: header.fields.len(),
53 got: i,
54 })?;
55
56 let count = *header.counts.get(i).unwrap_or(&1);
57
58 let value_type = match type_char {
59 'I' => match size_in_header {
60 1 => ValueType::I8,
61 2 => ValueType::I16,
62 4 => ValueType::I32,
63 _ => return Err(PcdError::UnsupportedType(format!("I{}", size_in_header))),
64 },
65 'U' => match size_in_header {
66 1 => ValueType::U8,
67 2 => ValueType::U16,
68 4 => ValueType::U32,
69 _ => return Err(PcdError::UnsupportedType(format!("U{}", size_in_header))),
70 },
71 'F' => match size_in_header {
72 4 => ValueType::F32,
73 8 => ValueType::F64,
74 _ => return Err(PcdError::UnsupportedType(format!("F{}", size_in_header))),
75 },
76 _ => return Err(PcdError::UnsupportedType(type_char.to_string())),
77 };
78
79 let element_size = value_type.size();
84 if element_size != size_in_header {
85 return Err(PcdError::LayoutMismatch {
86 expected: element_size,
87 got: size_in_header,
88 });
89 }
90
91 let field_size = element_size * count;
92
93 fields.push(FieldLayout {
94 name: name.clone(),
95 offset,
96 size: field_size,
97 element_size,
98 count,
99 type_: value_type,
100 });
101
102 offset += field_size;
103 }
104
105 Ok(PcdLayout {
106 fields,
107 total_size: offset,
108 })
109 }
110
111 pub fn get_field(&self, name: &str) -> Option<&FieldLayout> {
112 self.fields.iter().find(|f| f.name == name)
113 }
114}