1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <map>
20 #include <set>
21 #include <variant>
22 
23 #include "enum_def.h"
24 #include "field_list.h"
25 #include "fields/all_fields.h"
26 #include "fields/packet_field.h"
27 #include "parse_location.h"
28 #include "type_def.h"
29 
30 class ParentDef : public TypeDef {
31  public:
32   ParentDef(std::string name, FieldList fields);
33   ParentDef(std::string name, FieldList fields, ParentDef* parent);
34 
35   void AddParentConstraint(std::string field_name, std::variant<int64_t, std::string> value);
36 
37   void AddTestCase(std::string packet_bytes);
38 
39   // Assign all size fields to their corresponding variable length fields.
40   // Will crash if
41   //  - there aren't any fields that don't match up to a field.
42   //  - the size field points to a fixed size field.
43   //  - if the size field comes after the variable length field.
44   void AssignSizeFields();
45 
46   void SetEndianness(bool is_little_endian);
47 
48   // Get the size. You scan specify without_payload to exclude payload and body fields as children override them.
49   Size GetSize(bool without_payload = false) const;
50 
51   // Get the offset until the field is reached, if there is no field
52   // returns an empty Size. from_end requests the offset to the field
53   // starting from the end() iterator. If there is a field with an unknown
54   // size along the traversal, then an empty size is returned.
55   Size GetOffsetForField(std::string field_name, bool from_end = false) const;
56 
57   FieldList GetParamList() const;
58 
59   void GenMembers(std::ostream& s) const;
60 
61   void GenSize(std::ostream& s) const;
62 
63   void GenSerialize(std::ostream& s) const;
64 
65   void GenInstanceOf(std::ostream& s) const;
66 
67   const ParentDef* GetRootDef() const;
68 
69   bool HasAncestorNamed(std::string name) const;
70 
71   std::map<std::string, std::variant<int64_t, std::string>> GetAllConstraints() const;
72 
73   std::vector<const ParentDef*> GetAncestors() const;
74 
75   std::string FindConstraintField() const;
76 
77   std::map<const ParentDef*, const std::variant<int64_t, std::string>>
78       FindDescendantsWithConstraint(std::string constraint_name) const;
79   std::vector<const ParentDef*> FindPathToDescendant(std::string descendant) const;
80 
81   FieldList fields_;
82 
83   ParentDef* parent_{nullptr};
84 
85   ParentDef* complement_{nullptr};
86 
87   std::vector<ParentDef*> children_;
88 
89   std::set<std::string> test_cases_;
90   std::map<std::string, std::variant<int64_t, std::string>> parent_constraints_;
91   bool is_little_endian_;
92 
93   bool HasChildEnums() const;
94 
95   void GenRustWriteToFields(std::ostream& s) const;
96 
97   void GenSizeRetVal(std::ostream& s) const;
98 
99   void GenRustConformanceCheck(std::ostream& s) const;
100 };
101