rusty-gd: refine specialization

no need for accessors, define RCs that get loaded upon construction

Bug: 171749953
Tag: #gd-refactor
Test: gd/cert/run --rhost SimpleHalTest
Change-Id: I241bcf4e5f3ad95df37b4d0d3b174728965a4f7f
diff --git a/system/gd/packet/parser/packet_def.cc b/system/gd/packet/parser/packet_def.cc
index 7b3915a..20c2d56 100644
--- a/system/gd/packet/parser/packet_def.cc
+++ b/system/gd/packet/parser/packet_def.cc
@@ -744,7 +744,7 @@
   if (!children_.empty()) {
     s << "enum " << name_ << "DataChild {";
     for (const auto& child : children_) {
-      s << child->name_ << "(" << child->name_ << "Data),";
+      s << child->name_ << "(Rc<" << child->name_ << "Data>),";
     }
     s << "}\n";
     s << "pub enum " << name_ << "Child {";
@@ -777,7 +777,12 @@
   s << "}\n";
 
   s << "pub struct " << name_ << "Packet {";
-  s << "root: Rc<" << GetRootDef()->name_ << "Data>,";
+  auto lineage = GetAncestors();
+  lineage.push_back(this);
+  for (auto it = lineage.begin(); it != lineage.end(); it++) {
+    auto def = *it;
+    s << util::CamelCaseToUnderScore(def->name_) << ": Rc<" << def->name_ << "Data>,";
+  }
   s << "}\n";
 }
 
@@ -926,24 +931,43 @@
 
 void PacketDef::GenRustAccessStructImpls(std::ostream& s) const {
   s << "impl " << name_ << "Packet {";
+  auto root = GetRootDef();
   if (!children_.empty()) {
     s << " fn specialize(self) -> " << name_ << "Child {";
-    s << " match self.access_" << util::CamelCaseToUnderScore(name_) << "().child {";
+    s << " match self." << util::CamelCaseToUnderScore(name_) << ".child {";
     for (const auto& child : children_) {
       s << name_ << "DataChild::" << child->name_ << "(_) => " << name_ << "Child::" << child->name_ << "("
-        << child->name_ << "Packet::new(self.root)),";
+        << child->name_ << "Packet::new(self." << util::CamelCaseToUnderScore(root->name_) << ")),";
     }
     s << "}}";
   }
-  s << " fn new(root: Rc<" << GetRootDef()->name_ << "Data>) -> Self { unimplemented!(); }";
-
   auto lineage = GetAncestors();
   lineage.push_back(this);
+  const ParentDef* prev = nullptr;
+
+  s << " fn new(root: Rc<" << root->name_ << "Data>) -> Self {";
   for (auto it = lineage.begin(); it != lineage.end(); it++) {
     auto def = *it;
     auto accessor_name = util::CamelCaseToUnderScore(def->name_);
-    s << " fn access_" << accessor_name << "(&self) -> &" << def->name_ << "Data { unimplemented!(); }";
+    if (prev == nullptr) {
+      s << "let " << accessor_name << " = root;";
+    } else {
+      s << "let " << accessor_name << " = match &" << util::CamelCaseToUnderScore(prev->name_) << ".child {";
+      s << prev->name_ << "DataChild::" << def->name_ << "(value) => (*value).clone(),";
+      s << "_ => panic!(\"inconsistent state - child was not " << def->name_ << "\"),";
+      s << "};";
+    }
+    prev = def;
+  }
+  s << "Self {";
+  for (auto it = lineage.begin(); it != lineage.end(); it++) {
+    auto def = *it;
+    s << util::CamelCaseToUnderScore(def->name_) << ",";
+  }
+  s << "}}";
 
+  for (auto it = lineage.begin(); it != lineage.end(); it++) {
+    auto def = *it;
     auto fields = def->fields_.GetFieldsWithoutTypes({
         BodyField::kFieldType,
         CountField::kFieldType,
@@ -955,7 +979,7 @@
 
     for (auto const& field : fields) {
       s << "pub fn get_" << field->GetName() << "(&self) -> &" << field->GetRustDataType() << "{";
-      s << " &self.access_" << accessor_name << "()." << field->GetName();
+      s << " &self." << util::CamelCaseToUnderScore(def->name_) << ".as_ref()." << field->GetName();
       s << "}\n";
     }
   }
@@ -967,7 +991,7 @@
     auto def = *it;
     s << "impl Into<" << def->name_ << "Packet> for " << name_ << "Packet {";
     s << " fn into(self) -> " << def->name_ << "Packet {";
-    s << def->name_ << "Packet::new(self.root)";
+    s << def->name_ << "Packet::new(self." << util::CamelCaseToUnderScore(root->name_) << ")";
     s << " }";
     s << "}\n";
   }
diff --git a/system/gd/packet/parser/parent_def.cc b/system/gd/packet/parser/parent_def.cc
index f4e030b..ec939f6 100644
--- a/system/gd/packet/parser/parent_def.cc
+++ b/system/gd/packet/parser/parent_def.cc
@@ -498,5 +498,6 @@
     res.push_back(parent);
     parent = parent->parent_;
   }
+  std::reverse(res.begin(), res.end());
   return res;
 }