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