• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "perfetto/protozero/field.h"
18 
19 #include "perfetto/base/logging.h"
20 
21 #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
22 // The memcpy() for fixed32/64 below needs to be adjusted if we want to
23 // support big endian CPUs. There doesn't seem to be a compelling need today.
24 #error Unimplemented for big endian archs.
25 #endif
26 
27 namespace protozero {
28 
29 template <typename Container>
SerializeAndAppendToInternal(Container * dst) const30 void Field::SerializeAndAppendToInternal(Container* dst) const {
31   namespace pu = proto_utils;
32   size_t initial_size = dst->size();
33   dst->resize(initial_size + pu::kMaxSimpleFieldEncodedSize + size_);
34   uint8_t* start = reinterpret_cast<uint8_t*>(&(*dst)[initial_size]);
35   uint8_t* wptr = start;
36   switch (type_) {
37     case static_cast<int>(pu::ProtoWireType::kVarInt): {
38       wptr = pu::WriteVarInt(pu::MakeTagVarInt(id_), wptr);
39       wptr = pu::WriteVarInt(int_value_, wptr);
40       break;
41     }
42     case static_cast<int>(pu::ProtoWireType::kFixed32): {
43       wptr = pu::WriteVarInt(pu::MakeTagFixed<uint32_t>(id_), wptr);
44       uint32_t value32 = static_cast<uint32_t>(int_value_);
45       memcpy(wptr, &value32, sizeof(value32));
46       wptr += sizeof(uint32_t);
47       break;
48     }
49     case static_cast<int>(pu::ProtoWireType::kFixed64): {
50       wptr = pu::WriteVarInt(pu::MakeTagFixed<uint64_t>(id_), wptr);
51       memcpy(wptr, &int_value_, sizeof(int_value_));
52       wptr += sizeof(uint64_t);
53       break;
54     }
55     case static_cast<int>(pu::ProtoWireType::kLengthDelimited): {
56       ConstBytes payload = as_bytes();
57       wptr = pu::WriteVarInt(pu::MakeTagLengthDelimited(id_), wptr);
58       wptr = pu::WriteVarInt(payload.size, wptr);
59       memcpy(wptr, payload.data, payload.size);
60       wptr += payload.size;
61       break;
62     }
63     default:
64       PERFETTO_FATAL("Unknown field type %u", type_);
65   }
66   size_t written_size = static_cast<size_t>(wptr - start);
67   PERFETTO_DCHECK(written_size > 0 && written_size < pu::kMaxMessageLength);
68   PERFETTO_DCHECK(initial_size + written_size <= dst->size());
69   dst->resize(initial_size + written_size);
70 }
71 
SerializeAndAppendTo(std::string * dst) const72 void Field::SerializeAndAppendTo(std::string* dst) const {
73   SerializeAndAppendToInternal(dst);
74 }
75 
SerializeAndAppendTo(std::vector<uint8_t> * dst) const76 void Field::SerializeAndAppendTo(std::vector<uint8_t>* dst) const {
77   SerializeAndAppendToInternal(dst);
78 }
79 
80 }  // namespace protozero
81