rusty-gd: add support for struct fields in write_to()

Bug: 171749953
Tag: #gd-refactor
Test: gd/cert/run --rhost
Change-Id: I3f1a60733d2bf6bd77064523171f08dcb855ba7b
diff --git a/system/gd/packet/parser/fields/struct_field.cc b/system/gd/packet/parser/fields/struct_field.cc
index 0ec5af2..e41d74d 100644
--- a/system/gd/packet/parser/fields/struct_field.cc
+++ b/system/gd/packet/parser/fields/struct_field.cc
@@ -98,4 +98,6 @@
   s << start_offset.bytes() + GetSize().bytes() << "]).unwrap();";
 }
 
-void StructField::GenRustWriter(std::ostream&, Size, Size) const {}
+void StructField::GenRustWriter(std::ostream& s, Size, Size) const {
+  s << "self." << GetName() << ".write_to(buffer);";
+}
diff --git a/system/gd/packet/parser/struct_def.cc b/system/gd/packet/parser/struct_def.cc
index 71c09eb..5c6a670 100644
--- a/system/gd/packet/parser/struct_def.cc
+++ b/system/gd/packet/parser/struct_def.cc
@@ -438,6 +438,30 @@
   GenRustSizeField(s);
   s << "})}\n";
 
+  // write_to function
+  s << "fn write_to(&self, buffer: &mut BytesMut) {";
+  fields = fields_.GetFieldsWithoutTypes({
+      BodyField::kFieldType,
+      CountField::kFieldType,
+      PaddingField::kFieldType,
+      ReservedField::kFieldType,
+      SizeField::kFieldType,
+  });
+
+  for (auto const& field : fields) {
+    auto start_field_offset = GetOffsetForField(field->GetName(), false);
+    auto end_field_offset = GetOffsetForField(field->GetName(), true);
+
+    if (start_field_offset.empty() && end_field_offset.empty()) {
+      ERROR(field) << "Field location for " << field->GetName() << " is ambiguous, "
+                   << "no method exists to determine field location from begin() or end().\n";
+    }
+
+    field->GenRustWriter(s, start_field_offset, end_field_offset);
+  }
+
+  s << "}\n";
+
   if (fields.size() > 0) {
     s << "pub fn get_size(&self) -> usize { self.size }";
   }