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 pub fn new(name: Arc<str>, field_descs: Arc<Vec<GenericFieldDesc>>) -> Self {
62 Self {
63 name,
64 field_descs,
65 values: HashMap::new(),
66 }
67 }
68
69 pub fn set(mut self, name: &str, value: Vec<u8>) -> Self {
74 self.values.insert(name.to_string(), value);
75 self
76 }
77
78 pub fn set_u8(self, name: &str, value: u8) -> Self {
80 self.set(name, vec![value])
81 }
82
83 pub fn set_u16(self, name: &str, value: u16) -> Self {
85 self.set(name, value.to_be_bytes().to_vec())
86 }
87
88 pub fn set_u32(self, name: &str, value: u32) -> Self {
90 self.set(name, value.to_be_bytes().to_vec())
91 }
92
93 pub fn header_size(&self) -> usize {
95 self.field_descs.iter().map(|f| f.size).sum()
96 }
97
98 pub fn build(&self) -> Vec<u8> {
105 let total = self.header_size();
106 let mut buf = vec![0u8; total];
107
108 for field in self.field_descs.iter() {
109 let src: &[u8] = if let Some(v) = self.values.get(&field.name) {
110 v
111 } else {
112 &field.default_value
113 };
114
115 let dest_start = field.offset;
116 let dest_end = (field.offset + field.size).min(total);
117 let dest_slice = &mut buf[dest_start..dest_end];
118 let copy_len = src.len().min(dest_slice.len());
119
120 dest_slice[..copy_len].copy_from_slice(&src[..copy_len]);
122 }
123
124 buf
125 }
126
127 pub fn build_layer(&self) -> (GenericLayer, Vec<u8>) {
132 let buf = self.build();
133 let size = buf.len();
134 let index = LayerIndex::new(LayerKind::Generic, 0, size);
135 let layer = GenericLayer::new(index, self.name.clone(), self.field_descs.clone());
136 (layer, buf)
137 }
138
139 pub fn name(&self) -> &str {
141 &self.name
142 }
143
144 pub fn kind(&self) -> LayerKind {
146 LayerKind::Generic
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153 use crate::layer::field::FieldType;
154
155 fn make_fields() -> Arc<Vec<GenericFieldDesc>> {
156 Arc::new(vec![
157 GenericFieldDesc {
158 name: "type_id".to_string(),
159 offset: 0,
160 size: 2,
161 field_type: FieldType::U16,
162 default_value: vec![0x00, 0x01],
163 },
164 GenericFieldDesc {
165 name: "flags".to_string(),
166 offset: 2,
167 size: 1,
168 field_type: FieldType::U8,
169 default_value: vec![0xFF],
170 },
171 GenericFieldDesc {
172 name: "payload_len".to_string(),
173 offset: 3,
174 size: 4,
175 field_type: FieldType::U32,
176 default_value: vec![0x00, 0x00, 0x00, 0x00],
177 },
178 ])
179 }
180
181 #[test]
182 fn test_header_size() {
183 let fields = make_fields();
184 let builder = GenericLayerBuilder::new(Arc::from("Test"), fields);
185 assert_eq!(builder.header_size(), 7); }
187
188 #[test]
189 fn test_build_defaults() {
190 let fields = make_fields();
191 let builder = GenericLayerBuilder::new(Arc::from("Test"), fields);
192 let buf = builder.build();
193 assert_eq!(buf.len(), 7);
194 assert_eq!(buf[0], 0x00);
196 assert_eq!(buf[1], 0x01);
197 assert_eq!(buf[2], 0xFF);
199 assert_eq!(&buf[3..7], &[0x00, 0x00, 0x00, 0x00]);
201 }
202
203 #[test]
204 fn test_build_with_set_u16() {
205 let fields = make_fields();
206 let builder =
207 GenericLayerBuilder::new(Arc::from("Test"), fields).set_u16("type_id", 0xABCD);
208 let buf = builder.build();
209 assert_eq!(buf[0], 0xAB);
210 assert_eq!(buf[1], 0xCD);
211 assert_eq!(buf[2], 0xFF);
213 }
214
215 #[test]
216 fn test_build_with_set_u32() {
217 let fields = make_fields();
218 let builder =
219 GenericLayerBuilder::new(Arc::from("Test"), fields).set_u32("payload_len", 1024);
220 let buf = builder.build();
221 assert_eq!(&buf[3..7], &1024u32.to_be_bytes());
222 }
223
224 #[test]
225 fn test_build_truncation() {
226 let fields = Arc::new(vec![GenericFieldDesc {
227 name: "f".to_string(),
228 offset: 0,
229 size: 2,
230 field_type: FieldType::U16,
231 default_value: vec![0x00, 0x00],
232 }]);
233 let builder =
235 GenericLayerBuilder::new(Arc::from("T"), fields).set("f", vec![0xAA, 0xBB, 0xCC, 0xDD]);
236 let buf = builder.build();
237 assert_eq!(buf.len(), 2);
238 assert_eq!(buf[0], 0xAA);
239 assert_eq!(buf[1], 0xBB);
240 }
241
242 #[test]
243 fn test_build_zero_padding() {
244 let fields = Arc::new(vec![GenericFieldDesc {
245 name: "f".to_string(),
246 offset: 0,
247 size: 4,
248 field_type: FieldType::U32,
249 default_value: vec![0x00, 0x00, 0x00, 0x00],
250 }]);
251 let builder = GenericLayerBuilder::new(Arc::from("T"), fields).set("f", vec![0xAA]);
253 let buf = builder.build();
254 assert_eq!(buf, vec![0xAA, 0x00, 0x00, 0x00]);
255 }
256
257 #[test]
258 fn test_build_layer_returns_valid_layer() {
259 let fields = make_fields();
260 let builder = GenericLayerBuilder::new(Arc::from("MyProto"), fields);
261 let (layer, buf) = builder.build_layer();
262 assert_eq!(layer.index.start, 0);
263 assert_eq!(layer.index.end, 7);
264 assert_eq!(buf.len(), 7);
265 }
266
267 #[test]
268 fn test_kind() {
269 let fields = make_fields();
270 let builder = GenericLayerBuilder::new(Arc::from("T"), fields);
271 assert_eq!(builder.kind(), LayerKind::Generic);
272 }
273}