| /* |
| * Copyright (C) 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 "perfetto/protozero/field.h" |
| |
| #include "perfetto/base/compiler.h" |
| #include "perfetto/base/logging.h" |
| |
| #if !PERFETTO_IS_LITTLE_ENDIAN() |
| // The memcpy() for fixed32/64 below needs to be adjusted if we want to |
| // support big endian CPUs. There doesn't seem to be a compelling need today. |
| #error Unimplemented for big endian archs. |
| #endif |
| |
| namespace protozero { |
| |
| template <typename Container> |
| void Field::SerializeAndAppendToInternal(Container* dst) const { |
| namespace pu = proto_utils; |
| size_t initial_size = dst->size(); |
| dst->resize(initial_size + pu::kMaxSimpleFieldEncodedSize + size_); |
| uint8_t* start = reinterpret_cast<uint8_t*>(&(*dst)[initial_size]); |
| uint8_t* wptr = start; |
| switch (type_) { |
| case static_cast<int>(pu::ProtoWireType::kVarInt): { |
| wptr = pu::WriteVarInt(pu::MakeTagVarInt(id_), wptr); |
| wptr = pu::WriteVarInt(int_value_, wptr); |
| break; |
| } |
| case static_cast<int>(pu::ProtoWireType::kFixed32): { |
| wptr = pu::WriteVarInt(pu::MakeTagFixed<uint32_t>(id_), wptr); |
| uint32_t value32 = static_cast<uint32_t>(int_value_); |
| memcpy(wptr, &value32, sizeof(value32)); |
| wptr += sizeof(uint32_t); |
| break; |
| } |
| case static_cast<int>(pu::ProtoWireType::kFixed64): { |
| wptr = pu::WriteVarInt(pu::MakeTagFixed<uint64_t>(id_), wptr); |
| memcpy(wptr, &int_value_, sizeof(int_value_)); |
| wptr += sizeof(uint64_t); |
| break; |
| } |
| case static_cast<int>(pu::ProtoWireType::kLengthDelimited): { |
| ConstBytes payload = as_bytes(); |
| wptr = pu::WriteVarInt(pu::MakeTagLengthDelimited(id_), wptr); |
| wptr = pu::WriteVarInt(payload.size, wptr); |
| memcpy(wptr, payload.data, payload.size); |
| wptr += payload.size; |
| break; |
| } |
| default: |
| PERFETTO_FATAL("Unknown field type %u", type_); |
| } |
| size_t written_size = static_cast<size_t>(wptr - start); |
| PERFETTO_DCHECK(written_size > 0 && written_size < pu::kMaxMessageLength); |
| PERFETTO_DCHECK(initial_size + written_size <= dst->size()); |
| dst->resize(initial_size + written_size); |
| } |
| |
| void Field::SerializeAndAppendTo(std::string* dst) const { |
| SerializeAndAppendToInternal(dst); |
| } |
| |
| void Field::SerializeAndAppendTo(std::vector<uint8_t>* dst) const { |
| SerializeAndAppendToInternal(dst); |
| } |
| |
| } // namespace protozero |