1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/field.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/compiler.h"
20*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_IS_LITTLE_ENDIAN()
23*6dbdd20aSAndroid Build Coastguard Worker // The memcpy() for fixed32/64 below needs to be adjusted if we want to
24*6dbdd20aSAndroid Build Coastguard Worker // support big endian CPUs. There doesn't seem to be a compelling need today.
25*6dbdd20aSAndroid Build Coastguard Worker #error Unimplemented for big endian archs.
26*6dbdd20aSAndroid Build Coastguard Worker #endif
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker namespace protozero {
29*6dbdd20aSAndroid Build Coastguard Worker
30*6dbdd20aSAndroid Build Coastguard Worker template <typename Container>
SerializeAndAppendToInternal(Container * dst) const31*6dbdd20aSAndroid Build Coastguard Worker void Field::SerializeAndAppendToInternal(Container* dst) const {
32*6dbdd20aSAndroid Build Coastguard Worker namespace pu = proto_utils;
33*6dbdd20aSAndroid Build Coastguard Worker size_t initial_size = dst->size();
34*6dbdd20aSAndroid Build Coastguard Worker dst->resize(initial_size + pu::kMaxSimpleFieldEncodedSize + size_);
35*6dbdd20aSAndroid Build Coastguard Worker uint8_t* start = reinterpret_cast<uint8_t*>(&(*dst)[initial_size]);
36*6dbdd20aSAndroid Build Coastguard Worker uint8_t* wptr = start;
37*6dbdd20aSAndroid Build Coastguard Worker switch (type_) {
38*6dbdd20aSAndroid Build Coastguard Worker case static_cast<int>(pu::ProtoWireType::kVarInt): {
39*6dbdd20aSAndroid Build Coastguard Worker wptr = pu::WriteVarInt(pu::MakeTagVarInt(id_), wptr);
40*6dbdd20aSAndroid Build Coastguard Worker wptr = pu::WriteVarInt(int_value_, wptr);
41*6dbdd20aSAndroid Build Coastguard Worker break;
42*6dbdd20aSAndroid Build Coastguard Worker }
43*6dbdd20aSAndroid Build Coastguard Worker case static_cast<int>(pu::ProtoWireType::kFixed32): {
44*6dbdd20aSAndroid Build Coastguard Worker wptr = pu::WriteVarInt(pu::MakeTagFixed<uint32_t>(id_), wptr);
45*6dbdd20aSAndroid Build Coastguard Worker uint32_t value32 = static_cast<uint32_t>(int_value_);
46*6dbdd20aSAndroid Build Coastguard Worker memcpy(wptr, &value32, sizeof(value32));
47*6dbdd20aSAndroid Build Coastguard Worker wptr += sizeof(uint32_t);
48*6dbdd20aSAndroid Build Coastguard Worker break;
49*6dbdd20aSAndroid Build Coastguard Worker }
50*6dbdd20aSAndroid Build Coastguard Worker case static_cast<int>(pu::ProtoWireType::kFixed64): {
51*6dbdd20aSAndroid Build Coastguard Worker wptr = pu::WriteVarInt(pu::MakeTagFixed<uint64_t>(id_), wptr);
52*6dbdd20aSAndroid Build Coastguard Worker memcpy(wptr, &int_value_, sizeof(int_value_));
53*6dbdd20aSAndroid Build Coastguard Worker wptr += sizeof(uint64_t);
54*6dbdd20aSAndroid Build Coastguard Worker break;
55*6dbdd20aSAndroid Build Coastguard Worker }
56*6dbdd20aSAndroid Build Coastguard Worker case static_cast<int>(pu::ProtoWireType::kLengthDelimited): {
57*6dbdd20aSAndroid Build Coastguard Worker ConstBytes payload = as_bytes();
58*6dbdd20aSAndroid Build Coastguard Worker wptr = pu::WriteVarInt(pu::MakeTagLengthDelimited(id_), wptr);
59*6dbdd20aSAndroid Build Coastguard Worker wptr = pu::WriteVarInt(payload.size, wptr);
60*6dbdd20aSAndroid Build Coastguard Worker memcpy(wptr, payload.data, payload.size);
61*6dbdd20aSAndroid Build Coastguard Worker wptr += payload.size;
62*6dbdd20aSAndroid Build Coastguard Worker break;
63*6dbdd20aSAndroid Build Coastguard Worker }
64*6dbdd20aSAndroid Build Coastguard Worker default:
65*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL("Unknown field type %u", type_);
66*6dbdd20aSAndroid Build Coastguard Worker }
67*6dbdd20aSAndroid Build Coastguard Worker size_t written_size = static_cast<size_t>(wptr - start);
68*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(written_size > 0 && written_size < pu::kMaxMessageLength);
69*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(initial_size + written_size <= dst->size());
70*6dbdd20aSAndroid Build Coastguard Worker dst->resize(initial_size + written_size);
71*6dbdd20aSAndroid Build Coastguard Worker }
72*6dbdd20aSAndroid Build Coastguard Worker
SerializeAndAppendTo(std::string * dst) const73*6dbdd20aSAndroid Build Coastguard Worker void Field::SerializeAndAppendTo(std::string* dst) const {
74*6dbdd20aSAndroid Build Coastguard Worker SerializeAndAppendToInternal(dst);
75*6dbdd20aSAndroid Build Coastguard Worker }
76*6dbdd20aSAndroid Build Coastguard Worker
SerializeAndAppendTo(std::vector<uint8_t> * dst) const77*6dbdd20aSAndroid Build Coastguard Worker void Field::SerializeAndAppendTo(std::vector<uint8_t>* dst) const {
78*6dbdd20aSAndroid Build Coastguard Worker SerializeAndAppendToInternal(dst);
79*6dbdd20aSAndroid Build Coastguard Worker }
80*6dbdd20aSAndroid Build Coastguard Worker
81*6dbdd20aSAndroid Build Coastguard Worker } // namespace protozero
82