xref: /aosp_15_r20/external/pigweed/pw_protobuf/message.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2021 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/message.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <cstddef>
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/serialized_size.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/stream_decoder.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_result/result.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status_with_size.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/interval_reader.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/stream.h"
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker namespace pw::protobuf {
27*61c4878aSAndroid Build Coastguard Worker 
28*61c4878aSAndroid Build Coastguard Worker template <>
As()29*61c4878aSAndroid Build Coastguard Worker Uint32 Message::Field::As<Uint32>() {
30*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
31*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
32*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadUint32();
33*61c4878aSAndroid Build Coastguard Worker }
34*61c4878aSAndroid Build Coastguard Worker 
35*61c4878aSAndroid Build Coastguard Worker template <>
As()36*61c4878aSAndroid Build Coastguard Worker Int32 Message::Field::As<Int32>() {
37*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
38*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
39*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadInt32();
40*61c4878aSAndroid Build Coastguard Worker }
41*61c4878aSAndroid Build Coastguard Worker 
42*61c4878aSAndroid Build Coastguard Worker template <>
As()43*61c4878aSAndroid Build Coastguard Worker Sint32 Message::Field::As<Sint32>() {
44*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
45*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
46*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadSint32();
47*61c4878aSAndroid Build Coastguard Worker }
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker template <>
As()50*61c4878aSAndroid Build Coastguard Worker Fixed32 Message::Field::As<Fixed32>() {
51*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
52*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
53*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadFixed32();
54*61c4878aSAndroid Build Coastguard Worker }
55*61c4878aSAndroid Build Coastguard Worker 
56*61c4878aSAndroid Build Coastguard Worker template <>
As()57*61c4878aSAndroid Build Coastguard Worker Sfixed32 Message::Field::As<Sfixed32>() {
58*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
59*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
60*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadSfixed32();
61*61c4878aSAndroid Build Coastguard Worker }
62*61c4878aSAndroid Build Coastguard Worker 
63*61c4878aSAndroid Build Coastguard Worker template <>
As()64*61c4878aSAndroid Build Coastguard Worker Uint64 Message::Field::As<Uint64>() {
65*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
66*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
67*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadUint64();
68*61c4878aSAndroid Build Coastguard Worker }
69*61c4878aSAndroid Build Coastguard Worker 
70*61c4878aSAndroid Build Coastguard Worker template <>
As()71*61c4878aSAndroid Build Coastguard Worker Int64 Message::Field::As<Int64>() {
72*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
73*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
74*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadInt64();
75*61c4878aSAndroid Build Coastguard Worker }
76*61c4878aSAndroid Build Coastguard Worker 
77*61c4878aSAndroid Build Coastguard Worker template <>
As()78*61c4878aSAndroid Build Coastguard Worker Sint64 Message::Field::As<Sint64>() {
79*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
80*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
81*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadSint64();
82*61c4878aSAndroid Build Coastguard Worker }
83*61c4878aSAndroid Build Coastguard Worker 
84*61c4878aSAndroid Build Coastguard Worker template <>
As()85*61c4878aSAndroid Build Coastguard Worker Fixed64 Message::Field::As<Fixed64>() {
86*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
87*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
88*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadFixed64();
89*61c4878aSAndroid Build Coastguard Worker }
90*61c4878aSAndroid Build Coastguard Worker 
91*61c4878aSAndroid Build Coastguard Worker template <>
As()92*61c4878aSAndroid Build Coastguard Worker Sfixed64 Message::Field::As<Sfixed64>() {
93*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
94*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
95*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadSfixed64();
96*61c4878aSAndroid Build Coastguard Worker }
97*61c4878aSAndroid Build Coastguard Worker 
98*61c4878aSAndroid Build Coastguard Worker template <>
As()99*61c4878aSAndroid Build Coastguard Worker Float Message::Field::As<Float>() {
100*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
101*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
102*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadFloat();
103*61c4878aSAndroid Build Coastguard Worker }
104*61c4878aSAndroid Build Coastguard Worker 
105*61c4878aSAndroid Build Coastguard Worker template <>
As()106*61c4878aSAndroid Build Coastguard Worker Double Message::Field::As<Double>() {
107*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
108*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
109*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadDouble();
110*61c4878aSAndroid Build Coastguard Worker }
111*61c4878aSAndroid Build Coastguard Worker 
112*61c4878aSAndroid Build Coastguard Worker template <>
As()113*61c4878aSAndroid Build Coastguard Worker Bool Message::Field::As<Bool>() {
114*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(field_reader_.Reset());
115*61c4878aSAndroid Build Coastguard Worker   PW_TRY(decoder.Next());
116*61c4878aSAndroid Build Coastguard Worker   return decoder.ReadBool();
117*61c4878aSAndroid Build Coastguard Worker }
118*61c4878aSAndroid Build Coastguard Worker 
Equal(ConstByteSpan bytes)119*61c4878aSAndroid Build Coastguard Worker Result<bool> Bytes::Equal(ConstByteSpan bytes) {
120*61c4878aSAndroid Build Coastguard Worker   stream::IntervalReader bytes_reader = GetBytesReader();
121*61c4878aSAndroid Build Coastguard Worker   if (bytes_reader.interval_size() != bytes.size()) {
122*61c4878aSAndroid Build Coastguard Worker     return false;
123*61c4878aSAndroid Build Coastguard Worker   }
124*61c4878aSAndroid Build Coastguard Worker 
125*61c4878aSAndroid Build Coastguard Worker   std::byte buf[1];
126*61c4878aSAndroid Build Coastguard Worker   for (size_t i = 0; i < bytes.size();) {
127*61c4878aSAndroid Build Coastguard Worker     Result<ByteSpan> res = bytes_reader.Read(buf);
128*61c4878aSAndroid Build Coastguard Worker     PW_TRY(res.status());
129*61c4878aSAndroid Build Coastguard Worker     if (res.value().size() == 1) {
130*61c4878aSAndroid Build Coastguard Worker       if (buf[0] != bytes[i++])
131*61c4878aSAndroid Build Coastguard Worker         return false;
132*61c4878aSAndroid Build Coastguard Worker     }
133*61c4878aSAndroid Build Coastguard Worker   }
134*61c4878aSAndroid Build Coastguard Worker 
135*61c4878aSAndroid Build Coastguard Worker   return true;
136*61c4878aSAndroid Build Coastguard Worker }
137*61c4878aSAndroid Build Coastguard Worker 
Equal(std::string_view str)138*61c4878aSAndroid Build Coastguard Worker Result<bool> String::Equal(std::string_view str) {
139*61c4878aSAndroid Build Coastguard Worker   return Bytes::Equal(as_bytes(span<const char>{str}));
140*61c4878aSAndroid Build Coastguard Worker }
141*61c4878aSAndroid Build Coastguard Worker 
operator ++()142*61c4878aSAndroid Build Coastguard Worker Message::iterator& Message::iterator::operator++() {
143*61c4878aSAndroid Build Coastguard Worker   // If this is not a valid iterator, increment it to the end iterator,
144*61c4878aSAndroid Build Coastguard Worker   // so loop will end.
145*61c4878aSAndroid Build Coastguard Worker   if (!ok()) {
146*61c4878aSAndroid Build Coastguard Worker     reader_.Exhaust();
147*61c4878aSAndroid Build Coastguard Worker     eof_ = true;
148*61c4878aSAndroid Build Coastguard Worker     return *this;
149*61c4878aSAndroid Build Coastguard Worker   }
150*61c4878aSAndroid Build Coastguard Worker 
151*61c4878aSAndroid Build Coastguard Worker   // Store the starting offset of the field.
152*61c4878aSAndroid Build Coastguard Worker   size_t field_start = reader_.current();
153*61c4878aSAndroid Build Coastguard Worker   protobuf::StreamDecoder decoder(reader_);
154*61c4878aSAndroid Build Coastguard Worker   Status status = decoder.Next();
155*61c4878aSAndroid Build Coastguard Worker   if (status.IsOutOfRange()) {
156*61c4878aSAndroid Build Coastguard Worker     eof_ = true;
157*61c4878aSAndroid Build Coastguard Worker     return *this;
158*61c4878aSAndroid Build Coastguard Worker   } else if (!status.ok()) {
159*61c4878aSAndroid Build Coastguard Worker     // In the case of error, invalidate the iterator. We don't immediately
160*61c4878aSAndroid Build Coastguard Worker     // move the iterator to end(), so that calling code has a chance to catch
161*61c4878aSAndroid Build Coastguard Worker     // the error.
162*61c4878aSAndroid Build Coastguard Worker     status_ = status;
163*61c4878aSAndroid Build Coastguard Worker     current_ = Field(status_);
164*61c4878aSAndroid Build Coastguard Worker     return *this;
165*61c4878aSAndroid Build Coastguard Worker   }
166*61c4878aSAndroid Build Coastguard Worker 
167*61c4878aSAndroid Build Coastguard Worker   Result<uint32_t> field_number = decoder.FieldNumber();
168*61c4878aSAndroid Build Coastguard Worker   // Consume the field so that the reader will be pointing to the start
169*61c4878aSAndroid Build Coastguard Worker   // of the next field, which is equivalent to the end offset of the
170*61c4878aSAndroid Build Coastguard Worker   // current field.
171*61c4878aSAndroid Build Coastguard Worker   status = ConsumeCurrentField(decoder);
172*61c4878aSAndroid Build Coastguard Worker   if (!status.ok()) {
173*61c4878aSAndroid Build Coastguard Worker     status_ = status;
174*61c4878aSAndroid Build Coastguard Worker     current_ = Field(status_);
175*61c4878aSAndroid Build Coastguard Worker     return *this;
176*61c4878aSAndroid Build Coastguard Worker   }
177*61c4878aSAndroid Build Coastguard Worker 
178*61c4878aSAndroid Build Coastguard Worker   // Create a Field object with the field interval.
179*61c4878aSAndroid Build Coastguard Worker   current_ = Field(stream::IntervalReader(
180*61c4878aSAndroid Build Coastguard Worker                        reader_.source_reader(), field_start, reader_.current()),
181*61c4878aSAndroid Build Coastguard Worker                    field_number.value());
182*61c4878aSAndroid Build Coastguard Worker   return *this;
183*61c4878aSAndroid Build Coastguard Worker }
184*61c4878aSAndroid Build Coastguard Worker 
begin()185*61c4878aSAndroid Build Coastguard Worker Message::iterator Message::begin() {
186*61c4878aSAndroid Build Coastguard Worker   if (!ok()) {
187*61c4878aSAndroid Build Coastguard Worker     return end();
188*61c4878aSAndroid Build Coastguard Worker   }
189*61c4878aSAndroid Build Coastguard Worker 
190*61c4878aSAndroid Build Coastguard Worker   return iterator(reader_.Reset());
191*61c4878aSAndroid Build Coastguard Worker }
192*61c4878aSAndroid Build Coastguard Worker 
end()193*61c4878aSAndroid Build Coastguard Worker Message::iterator Message::end() {
194*61c4878aSAndroid Build Coastguard Worker   // The end iterator is created by using an exahusted stream::IntervalReader,
195*61c4878aSAndroid Build Coastguard Worker   // i.e. the reader is pointing at the internval end.
196*61c4878aSAndroid Build Coastguard Worker   stream::IntervalReader reader_end = reader_;
197*61c4878aSAndroid Build Coastguard Worker   return iterator(reader_end.Exhaust());
198*61c4878aSAndroid Build Coastguard Worker }
199*61c4878aSAndroid Build Coastguard Worker 
AsRepeatedBytes(uint32_t field_number)200*61c4878aSAndroid Build Coastguard Worker RepeatedBytes Message::AsRepeatedBytes(uint32_t field_number) {
201*61c4878aSAndroid Build Coastguard Worker   return AsRepeated<Bytes>(field_number);
202*61c4878aSAndroid Build Coastguard Worker }
203*61c4878aSAndroid Build Coastguard Worker 
AsRepeatedStrings(uint32_t field_number)204*61c4878aSAndroid Build Coastguard Worker RepeatedFieldParser<String> Message::AsRepeatedStrings(uint32_t field_number) {
205*61c4878aSAndroid Build Coastguard Worker   return AsRepeated<String>(field_number);
206*61c4878aSAndroid Build Coastguard Worker }
207*61c4878aSAndroid Build Coastguard Worker 
AsRepeatedMessages(uint32_t field_number)208*61c4878aSAndroid Build Coastguard Worker RepeatedFieldParser<Message> Message::AsRepeatedMessages(
209*61c4878aSAndroid Build Coastguard Worker     uint32_t field_number) {
210*61c4878aSAndroid Build Coastguard Worker   return AsRepeated<Message>(field_number);
211*61c4878aSAndroid Build Coastguard Worker }
212*61c4878aSAndroid Build Coastguard Worker 
AsStringToMessageMap(uint32_t field_number)213*61c4878aSAndroid Build Coastguard Worker StringMapParser<Message> Message::AsStringToMessageMap(uint32_t field_number) {
214*61c4878aSAndroid Build Coastguard Worker   return AsStringMap<Message>(field_number);
215*61c4878aSAndroid Build Coastguard Worker }
216*61c4878aSAndroid Build Coastguard Worker 
AsStringToBytesMap(uint32_t field_number)217*61c4878aSAndroid Build Coastguard Worker StringMapParser<Bytes> Message::AsStringToBytesMap(uint32_t field_number) {
218*61c4878aSAndroid Build Coastguard Worker   return AsStringMap<Bytes>(field_number);
219*61c4878aSAndroid Build Coastguard Worker }
220*61c4878aSAndroid Build Coastguard Worker 
AsStringToStringMap(uint32_t field_number)221*61c4878aSAndroid Build Coastguard Worker StringMapParser<String> Message::AsStringToStringMap(uint32_t field_number) {
222*61c4878aSAndroid Build Coastguard Worker   return AsStringMap<String>(field_number);
223*61c4878aSAndroid Build Coastguard Worker }
224*61c4878aSAndroid Build Coastguard Worker 
225*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::protobuf
226