stackforge_core/layer/generic/
builder.rs1use std::collections::HashMap;
4use std::sync::Arc;
5
6use super::{GenericFieldDesc, GenericLayer};
7use crate::layer::{LayerIndex, LayerKind};
8
9#[derive(Debug, Clone)]
50pub struct GenericLayerBuilder {
51 name: Arc<str>,
53 field_descs: Arc<Vec<GenericFieldDesc>>,
55 values: HashMap<String, Vec<u8>>,
57}
58
59impl GenericLayerBuilder {
60 #[must_use]
62 pub fn new(name: Arc<str>, field_descs: Arc<Vec<GenericFieldDesc>>) -> Self {
63 Self {
64 name,
65 field_descs,
66 values: HashMap::new(),
67 }
68 }
69
70 #[must_use]
75 pub fn set(mut self, name: &str, value: Vec<u8>) -> Self {
76 self.values.insert(name.to_string(), value);
77 self
78 }
79
80 #[must_use]
82 pub fn set_u8(self, name: &str, value: u8) -> Self {
83 self.set(name, vec![value])
84 }
85
86 #[must_use]
88 pub fn set_u16(self, name: &str, value: u16) -> Self {
89 self.set(name, value.to_be_bytes().to_vec())
90 }
91
92 #[must_use]
94 pub fn set_u32(self, name: &str, value: u32) -> Self {
95 self.set(name, value.to_be_bytes().to_vec())
96 }
97
98 #[must_use]
100 pub fn header_size(&self) -> usize {
101 self.field_descs.iter().map(|f| f.size).sum()
102 }
103
104 #[must_use]
111 pub fn build(&self) -> Vec<u8> {
112 let total = self.header_size();
113 let mut buf = vec![0u8; total];
114
115 for field in self.field_descs.iter() {
116 let src: &[u8] = if let Some(v) = self.values.get(&field.name) {
117 v
118 } else {
119 &field.default_value
120 };
121
122 let dest_start = field.offset;
123 let dest_end = (field.offset + field.size).min(total);
124 let dest_slice = &mut buf[dest_start..dest_end];
125 let copy_len = src.len().min(dest_slice.len());
126
127 dest_slice[..copy_len].copy_from_slice(&src[..copy_len]);
129 }
130
131 buf
132 }
133
134 #[must_use]
139 pub fn build_layer(&self) -> (GenericLayer, Vec<u8>) {
140 let buf = self.build();
141 let size = buf.len();
142 let index = LayerIndex::new(LayerKind::Generic, 0, size);
143 let layer = GenericLayer::new(index, self.name.clone(), self.field_descs.clone());
144 (layer, buf)
145 }
146
147 #[must_use]
149 pub fn name(&self) -> &str {
150 &self.name
151 }
152
153 #[must_use]
155 pub fn kind(&self) -> LayerKind {
156 LayerKind::Generic
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::layer::field::FieldType;
164
165 fn make_fields() -> Arc<Vec<GenericFieldDesc>> {
166 Arc::new(vec![
167 GenericFieldDesc {
168 name: "type_id".to_string(),
169 offset: 0,
170 size: 2,
171 field_type: FieldType::U16,
172 default_value: vec![0x00, 0x01],
173 },
174 GenericFieldDesc {
175 name: "flags".to_string(),
176 offset: 2,
177 size: 1,
178 field_type: FieldType::U8,
179 default_value: vec![0xFF],
180 },
181 GenericFieldDesc {
182 name: "payload_len".to_string(),
183 offset: 3,
184 size: 4,
185 field_type: FieldType::U32,
186 default_value: vec![0x00, 0x00, 0x00, 0x00],
187 },
188 ])
189 }
190
191 #[test]
192 fn test_header_size() {
193 let fields = make_fields();
194 let builder = GenericLayerBuilder::new(Arc::from("Test"), fields);
195 assert_eq!(builder.header_size(), 7); }
197
198 #[test]
199 fn test_build_defaults() {
200 let fields = make_fields();
201 let builder = GenericLayerBuilder::new(Arc::from("Test"), fields);
202 let buf = builder.build();
203 assert_eq!(buf.len(), 7);
204 assert_eq!(buf[0], 0x00);
206 assert_eq!(buf[1], 0x01);
207 assert_eq!(buf[2], 0xFF);
209 assert_eq!(&buf[3..7], &[0x00, 0x00, 0x00, 0x00]);
211 }
212
213 #[test]
214 fn test_build_with_set_u16() {
215 let fields = make_fields();
216 let builder =
217 GenericLayerBuilder::new(Arc::from("Test"), fields).set_u16("type_id", 0xABCD);
218 let buf = builder.build();
219 assert_eq!(buf[0], 0xAB);
220 assert_eq!(buf[1], 0xCD);
221 assert_eq!(buf[2], 0xFF);
223 }
224
225 #[test]
226 fn test_build_with_set_u32() {
227 let fields = make_fields();
228 let builder =
229 GenericLayerBuilder::new(Arc::from("Test"), fields).set_u32("payload_len", 1024);
230 let buf = builder.build();
231 assert_eq!(&buf[3..7], &1024u32.to_be_bytes());
232 }
233
234 #[test]
235 fn test_build_truncation() {
236 let fields = Arc::new(vec![GenericFieldDesc {
237 name: "f".to_string(),
238 offset: 0,
239 size: 2,
240 field_type: FieldType::U16,
241 default_value: vec![0x00, 0x00],
242 }]);
243 let builder =
245 GenericLayerBuilder::new(Arc::from("T"), fields).set("f", vec![0xAA, 0xBB, 0xCC, 0xDD]);
246 let buf = builder.build();
247 assert_eq!(buf.len(), 2);
248 assert_eq!(buf[0], 0xAA);
249 assert_eq!(buf[1], 0xBB);
250 }
251
252 #[test]
253 fn test_build_zero_padding() {
254 let fields = Arc::new(vec![GenericFieldDesc {
255 name: "f".to_string(),
256 offset: 0,
257 size: 4,
258 field_type: FieldType::U32,
259 default_value: vec![0x00, 0x00, 0x00, 0x00],
260 }]);
261 let builder = GenericLayerBuilder::new(Arc::from("T"), fields).set("f", vec![0xAA]);
263 let buf = builder.build();
264 assert_eq!(buf, vec![0xAA, 0x00, 0x00, 0x00]);
265 }
266
267 #[test]
268 fn test_build_layer_returns_valid_layer() {
269 let fields = make_fields();
270 let builder = GenericLayerBuilder::new(Arc::from("MyProto"), fields);
271 let (layer, buf) = builder.build_layer();
272 assert_eq!(layer.index.start, 0);
273 assert_eq!(layer.index.end, 7);
274 assert_eq!(buf.len(), 7);
275 }
276
277 #[test]
278 fn test_kind() {
279 let fields = make_fields();
280 let builder = GenericLayerBuilder::new(Arc::from("T"), fields);
281 assert_eq!(builder.kind(), LayerKind::Generic);
282 }
283}