Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_rpc / packet.cc
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_rpc/internal/packet.h"
16
17 #include "pw_protobuf/decoder.h"
18
19 namespace pw::rpc::internal {
20
21 using std::byte;
22
23 Result<Packet> Packet::FromBuffer(ConstByteSpan data) {
24   Packet packet;
25   Status status;
26   protobuf::Decoder decoder(data);
27
28   while ((status = decoder.Next()).ok()) {
29     RpcPacket::Fields field =
30         static_cast<RpcPacket::Fields>(decoder.FieldNumber());
31
32     switch (field) {
33       case RpcPacket::Fields::TYPE: {
34         uint32_t value;
35         decoder.ReadUint32(&value);
36         packet.set_type(static_cast<PacketType>(value));
37         break;
38       }
39
40       case RpcPacket::Fields::CHANNEL_ID:
41         decoder.ReadUint32(&packet.channel_id_);
42         break;
43
44       case RpcPacket::Fields::SERVICE_ID:
45         decoder.ReadFixed32(&packet.service_id_);
46         break;
47
48       case RpcPacket::Fields::METHOD_ID:
49         decoder.ReadFixed32(&packet.method_id_);
50         break;
51
52       case RpcPacket::Fields::PAYLOAD:
53         decoder.ReadBytes(&packet.payload_);
54         break;
55
56       case RpcPacket::Fields::STATUS: {
57         uint32_t value;
58         decoder.ReadUint32(&value);
59         packet.set_status(static_cast<Status::Code>(value));
60         break;
61       }
62     }
63   }
64
65   if (status.IsDataLoss()) {
66     return status;
67   }
68
69   return packet;
70 }
71
72 Result<ConstByteSpan> Packet::Encode(ByteSpan buffer) const {
73   pw::protobuf::NestedEncoder encoder(buffer);
74   RpcPacket::Encoder rpc_packet(&encoder);
75
76   // The payload is encoded first, as it may share the encode buffer.
77   rpc_packet.WritePayload(payload_);
78
79   rpc_packet.WriteType(type_);
80   rpc_packet.WriteChannelId(channel_id_);
81   rpc_packet.WriteServiceId(service_id_);
82   rpc_packet.WriteMethodId(method_id_);
83   rpc_packet.WriteStatus(status_.code());
84
85   return encoder.Encode();
86 }
87
88 size_t Packet::MinEncodedSizeBytes() const {
89   size_t reserved_size = 0;
90
91   reserved_size += 1;  // channel_id key
92   reserved_size += varint::EncodedSize(channel_id());
93   reserved_size += 1 + sizeof(uint32_t);  // service_id key and fixed32
94   reserved_size += 1 + sizeof(uint32_t);  // method_id key and fixed32
95
96   // Packet type always takes two bytes to encode (varint key + varint enum).
97   reserved_size += 2;
98
99   // Status field always takes two bytes to encode (varint key + varint status).
100   reserved_size += 2;
101
102   // Payload field takes at least two bytes to encode (varint key + length).
103   reserved_size += 2;
104
105   return reserved_size;
106 }
107
108 }  // namespace pw::rpc::internal