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