/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "fields/payload_field.h" #include "util.h" const std::string PayloadField::kFieldType = "PayloadField"; PayloadField::PayloadField(std::string modifier, ParseLocation loc) : PacketField("payload", loc), size_field_(nullptr), size_modifier_(modifier) {} void PayloadField::SetSizeField(const SizeField* size_field) { if (size_field_ != nullptr) { ERROR(this, size_field_, size_field) << "The size field for the payload has already been assigned."; } size_field_ = size_field; } const std::string& PayloadField::GetFieldType() const { return PayloadField::kFieldType; } Size PayloadField::GetSize() const { if (size_field_ == nullptr) { if (!size_modifier_.empty()) { ERROR(this) << "Missing size field for payload with size modifier."; } return Size(); } std::string dynamic_size = "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * 8)"; if (!size_modifier_.empty()) { dynamic_size += "- (" + size_modifier_ + ")"; } return dynamic_size; } std::string PayloadField::GetDataType() const { return "PacketView"; } void PayloadField::GenExtractor(std::ostream&, int, bool) const { ERROR(this) << __func__ << " should never be called. "; } std::string PayloadField::GetGetterFunctionName() const { return "GetPayload"; } void PayloadField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const { s << "PacketView " << GetGetterFunctionName() << "() const {"; s << "ASSERT(was_validated_);"; s << "size_t end_index = size();"; s << "auto to_bound = begin();"; GenBounds(s, start_offset, end_offset, GetSize()); s << "return GetLittleEndianSubview(field_begin, field_end);"; s << "}\n\n"; s << "PacketView " << GetGetterFunctionName() << "BigEndian() const {"; s << "ASSERT(was_validated_);"; s << "size_t end_index = size();"; s << "auto to_bound = begin();"; GenBounds(s, start_offset, end_offset, GetSize()); s << "return GetBigEndianSubview(field_begin, field_end);"; s << "}\n"; } std::string PayloadField::GetBuilderParameterType() const { return "std::unique_ptr"; } bool PayloadField::BuilderParameterMustBeMoved() const { return true; } void PayloadField::GenBuilderParameterFromView(std::ostream& s) const { s << "std::make_unique(std::vector(view.GetPayload().begin(), view.GetPayload().end()))"; } bool PayloadField::HasParameterValidator() const { return false; } void PayloadField::GenParameterValidator(std::ostream&) const { // There is no validation needed for a payload } void PayloadField::GenInserter(std::ostream&) const { ERROR() << __func__ << " Should never be called."; } void PayloadField::GenValidator(std::ostream&) const { // Do nothing } void PayloadField::GenStringRepresentation(std::ostream& s, std::string) const { // TODO: we should parse the child packets s << "\"PAYLOAD[]\""; } std::string PayloadField::GetRustDataType() const { return "Vec::"; } void PayloadField::GenRustGetter(std::ostream& s, Size start_offset, Size) const { s << "let " << GetName() << ": " << GetRustDataType() << " = "; if (size_field_ == nullptr) { s << "bytes[" << start_offset.bytes() << "..].into();"; } else { s << "bytes[" << start_offset.bytes() << "..("; s << start_offset.bytes() << " + " << size_field_->GetName() << " as usize)].into();"; } } void PayloadField::GenRustWriter(std::ostream&, Size, Size) const {}