File indexing completed on 2025-06-29 04:47:08

0001 /*
0002     SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #ifndef KITINERARY_PROTOBUFSTREAMREADER_H
0007 #define KITINERARY_PROTOBUFSTREAMREADER_H
0008 
0009 #include <QByteArray>
0010 #include <QMetaType>
0011 
0012 #include <string_view>
0013 
0014 class QString;
0015 
0016 namespace KItinerary {
0017 
0018 /** Protocol Buffers stream reader.
0019  *  For use on protobuf data for which the full format definition is unknown.
0020  *  @see https://protobuf.dev/
0021  */
0022 class ProtobufStreamReader
0023 {
0024     Q_GADGET
0025 public:
0026     explicit ProtobufStreamReader();
0027     explicit ProtobufStreamReader(std::string_view data);
0028     explicit ProtobufStreamReader(const QByteArray &data);
0029     ~ProtobufStreamReader();
0030 
0031     /** Returns the number of the current field.
0032      *  Assumes the cursor is on the beginning of a field. The cursor does not advance.
0033      */
0034     Q_INVOKABLE quint64 fieldNumber();
0035 
0036     enum WireType {
0037         VARINT,
0038         I64,
0039         LEN,
0040         SGROUP,
0041         EGROUP,
0042         I32,
0043     };
0044     Q_ENUM(WireType)
0045 
0046     /** Returns the wire type of the current field.
0047      *  Assumes the cursor is on the beginning of a field. The cursor does not advance.
0048      */
0049     Q_INVOKABLE WireType wireType();
0050 
0051     /** Read a field of type VARINT.
0052      *  This assumes the cursor is placed at the beginning of a field with wire type VARINT.
0053      *  The cursor is advanced to after the field.
0054      */
0055     Q_INVOKABLE quint64 readVarintField();
0056 
0057     /** Reads a field of type LEN.
0058      *  This assumes the cursor is placed at the beginning of a field with wire type LEN.
0059      *  The cursor is advanced to after the field.
0060      */
0061     std::string_view readLengthDelimitedRecord();
0062 
0063     /** Reads a string.
0064      *  This assumes the cursor is placed at the beginning of a field with wire type LEN
0065      *  containing a string. The cursor is advanced to after the field.
0066      */
0067     Q_INVOKABLE QString readString();
0068 
0069     /** Reads a nested message.
0070      *  This assumes the cursor is placed at the beginning of a field with wire type LEN
0071      *  containing a sub-message. The cursor is advanced to after the field.
0072      */
0073     Q_INVOKABLE KItinerary::ProtobufStreamReader readSubMessage();
0074 
0075     /** Returns @c true when having reached the end of the stream. */
0076     Q_INVOKABLE bool atEnd() const;
0077 
0078     /** Skips over the next field in the stream. */
0079     Q_INVOKABLE void skip();
0080 
0081     ///@cond internal
0082     /** Read Base 128 varint value from the current stream position and advances the cursor. */
0083     uint64_t readVarint();
0084     /** Read Base 128 varint value from the current stream position without advancing the cursor. */
0085     uint64_t peekVarint();
0086     ///@endcond
0087 
0088 private:
0089     QByteArray m_ownedData;
0090     std::string_view m_data;
0091     std::string_view::size_type m_cursor = 0;
0092 };
0093 
0094 }
0095 
0096 #endif // KITINERARY_PROTOBUFSTREAMREADER_H