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 #include "fields/packet_field.h"
18
19 #include "util.h"
20
PacketField(std::string name,ParseLocation loc)21 PacketField::PacketField(std::string name, ParseLocation loc) : loc_(loc), name_(name) {}
22
GetDebugName() const23 std::string PacketField::GetDebugName() const {
24 return "Field{Type:" + GetFieldType() + ", Name:" + GetName() + "}";
25 }
26
GetLocation() const27 ParseLocation PacketField::GetLocation() const {
28 return loc_;
29 }
30
GetName() const31 std::string PacketField::GetName() const {
32 return name_;
33 }
34
GetBuilderSize() const35 Size PacketField::GetBuilderSize() const {
36 return GetSize();
37 }
38
GetStructSize() const39 Size PacketField::GetStructSize() const {
40 return GetSize();
41 }
42
GenBounds(std::ostream & s,Size start_offset,Size end_offset,Size size) const43 int PacketField::GenBounds(std::ostream& s, Size start_offset, Size end_offset, Size size) const {
44 // In order to find field_begin and field_end, we must have two of the three Sizes.
45 if ((start_offset.empty() && size.empty()) || (start_offset.empty() && end_offset.empty()) ||
46 (end_offset.empty() && size.empty())) {
47 ERROR(this) << "GenBounds called without enough information. " << start_offset << end_offset << size;
48 }
49
50 if (start_offset.bits() % 8 != 0 || end_offset.bits() % 8 != 0) {
51 ERROR(this) << "Can not find the bounds of a field at a non byte-aligned offset." << start_offset << end_offset;
52 }
53
54 if (!start_offset.empty()) {
55 s << "size_t field_begin = (" << start_offset << ") / 8;";
56 } else {
57 s << "size_t field_begin = end_index - (" << end_offset << " + " << size << ") / 8;";
58 }
59
60 if (!end_offset.empty()) {
61 s << "size_t field_end = end_index - (" << end_offset << ") / 8;";
62 // If the field has a known size, use the minimum for the end
63 if (!size.empty()) {
64 s << "size_t field_sized_end = field_begin + (" << size << ") / 8;";
65 s << "if (field_sized_end < field_end) { field_end = field_sized_end; }";
66 }
67 } else {
68 s << "size_t field_end = field_begin + (" << size << ") / 8;";
69 s << "if (field_end > end_index) { field_end = end_index; }";
70 }
71 s << "auto " << name_ << "_it = to_bound.Subrange(field_begin, field_end - field_begin); ";
72 return 0; // num_leading_bits
73 }
74
GenBuilderParameter(std::ostream & s) const75 bool PacketField::GenBuilderParameter(std::ostream& s) const {
76 auto param_type = GetBuilderParameterType();
77 if (param_type.empty()) {
78 return false;
79 }
80 s << param_type << " " << GetName();
81 return true;
82 }
83
BuilderParameterMustBeMoved() const84 bool PacketField::BuilderParameterMustBeMoved() const {
85 return false;
86 }
87
GenBuilderMember(std::ostream & s) const88 bool PacketField::GenBuilderMember(std::ostream& s) const {
89 return GenBuilderParameter(s);
90 }
91
GenBuilderParameterFromView(std::ostream & s) const92 void PacketField::GenBuilderParameterFromView(std::ostream& s) const {
93 s << "view.Get" << util::UnderscoreToCamelCase(GetName()) << "()";
94 }
95
IsContainerField() const96 bool PacketField::IsContainerField() const {
97 return false;
98 }
99
GetElementField() const100 const PacketField* PacketField::GetElementField() const {
101 return nullptr;
102 }
103
GenStringRepresentation(std::ostream & s,std::string accessor) const104 void PacketField::GenStringRepresentation(std::ostream& s, std::string accessor) const {
105 s << "\"REPRESENTATION_UNIMPLEMENTED " << GetFieldType() << " " << accessor << "\"";
106 }
107
GetRustBitOffset(std::ostream &,Size start_offset,Size end_offset,Size size) const108 int PacketField::GetRustBitOffset(
109 std::ostream&, Size start_offset, Size end_offset, Size size) const {
110 // In order to find field_begin and field_end, we must have two of the three Sizes.
111 if ((start_offset.empty() && size.empty()) || (start_offset.empty() && end_offset.empty()) ||
112 (end_offset.empty() && size.empty())) {
113 ERROR(this) << "GenBounds called without enough information. "
114 << start_offset << end_offset << size;
115 }
116
117 if (start_offset.bits() % 8 != 0 || end_offset.bits() % 8 != 0) {
118 ERROR(this) << "Can not find the bounds of a field at a non byte-aligned offset."
119 << start_offset << end_offset;
120 }
121
122 return 0; // num_leading_bits
123 }
124
GenRustNameAndType(std::ostream & s) const125 bool PacketField::GenRustNameAndType(std::ostream& s) const {
126 auto param_type = GetRustDataType();
127 if (param_type.empty()) {
128 return false;
129 }
130 s << GetName() << ": " << param_type;
131 return true;
132 }
133
GenBoundsCheck(std::ostream & s,Size start_offset,Size,std::string context) const134 void PacketField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string context) const {
135 Size size = GetSize();
136 if (size.bits() < 8) {
137 return;
138 }
139 s << "if bytes.len() < " << start_offset.bytes() + size.bytes() << " {";
140 s << " return Err(Error::InvalidLengthError{";
141 s << " obj: \"" << context << "\".to_string(),";
142 s << " field: \"" << GetName() << "\".to_string(),";
143 s << " wanted: " << start_offset.bytes() + size.bytes() << ",";
144 s << " got: bytes.len()});";
145 s << "}";
146 }
147